编程技术网

关注微信公众号,定时推送前沿、专业、深度的编程技术资料。

 找回密码
 立即注册

QQ登录

只需一步,快速开始

多个NSThreads同步:Multiple NSThreads synchronization

Ghostvv 线程 2022-5-20 12:31 178人围观

腾讯云服务器
多个NSThreads同步的处理方法

我想使用NSThread

我有一个主线程和三(3)个workerThread T1,T2,T3.所有这些都是从主线程同时启动的,主线程有一个int size变量.现在,我想以所有方式同步所有三个线程,当我执行上述每个线程时,它将打印以下内容:

I've a main thread and three (3) workerThread T1, T2, T3. All these started at the same time from main thread, Main thread has an int size variable. Now I want to synchronize all three threads in a way they, when my each of the above threads will execute, it will print the following:

//在主线程中

- (void) mainFunction{ size = 0; NSThread* T1 = [[NSThread alloc] initWithTarget:self selector:@selector(workerThread:) object:@"T1"]; [T1 start]; NSThread* T2 = [[NSThread alloc] initWithTarget:self selector:@selector(workerThread:) object:@"T2"]; [T2 start]; NSThread* T3 = [[NSThread alloc] initWithTarget:self selector:@selector(workerThread:) object:@"T3"]; [T3 start]; } 

//工作线程

- (void) workerThread:(id)obj{ size++; NSLog(@"Thread:%@--------Size:%d,obj,size) } 

我想要以下输出:

Thread:T1-------Size:1 Thread:T2-------Size:2 Thread:T3-------Size:3 Thread:T1-------Size:4 Thread:T2-------Size:5 Thread:T3-------Size:6 Thread:T1-------Size:7 Thread:T2-------Size:8 Thread:T3-------Size:9 

,并在size=10

问题解答

一些想法:

  1. 您说当size = 10时将控制权返回到主线程".那根本没有道理.主线程永远不会丢失"控件(因为这些线程是同时发生的).也许当这种情况出现时,您希望在主线程上发生什么事情?

  1. You say "return control back to main thread when size=10". That doesn't quite make sense. The main thread never "lost" control (as these threads are happening concurrently). Perhaps you wanted something to happen on the main thread when this situation arose?

您没有让workerThread方法执行任何循环,因此在编写该循环时,每个线程都会执行一次此循环然后退出.您可能需要在此处添加某种形式的循环.

You're not having the workerThread method do any looping, so as you've written it, each thread will do this once and then quit. You probably need to add some form of loop here.

即使添加了循环,所需的输出也表明您正在假设将要执行的特定操作序列,即这三个线程将按顺序运行(但您没有这样的保证).如果您需要这种行为,则可以设置一系列信号量,通过这些信号量,您可以让一个线程等待另一个线程发送的信号.

Even if you added looping, your desired output suggests that you're assuming a particular sequence of actions that would take place, namely that these three threads will run in order (but you have no such assurances). If you needed that behavior, you'd set up a series of semaphores by which you could have one thread waiting for a signal to be sent by another.

从不同线程更新变量时应小心.请参阅在处理诸如计数器之类的基本数据类型时,它得到了简化(只需确保将其声明为atomic).但是在更实质性的情况下,您将需要使用一些同步技术,例如@synchronized,锁,专用的自定义串行队列等.

You should be careful when updating a variable from different threads. See the Synchronization section of the Threading Programming Guide. It's simplified when dealing with a fundamental data type like your counter (just make sure you declare it as atomic). But in more substantive scenarios, you'll want to employ some synchronization technique such as @synchronized, locks, dedicated custom serial queue, etc.

通常,如果您正在使用线程(但如果使用队列则不是必需的),则应为

In general, if you're using threads (but not necessary if using queues), you should be creating an autorelease pool for your thread.

无论如何,撇开这些观察,您可能会有类似以下的内容,其中(a)的内容为@autoreleasepool; (b)循环; (c)使用锁来确保各个线程将其交互与size变量同步:

Anyway, with these observations aside, you might have something like the following, which (a) has @autoreleasepool; (b) loops; and (c) uses a lock to make sure that the various threads synchronize their interactions with the size variable:

- (void) workerThread:(id)obj { @autoreleasepool { BOOL done = NO; while (!done) { [self.lock lock]; if (size < 9) { size++; NSLog(@"Thread:%@--------Size:%d", obj, size); } else { done = YES; } [self.lock unlock]; // perhaps you're doing something time consuming here... } } } 

这假定您具有名为lockNSLock属性:

This assumes you have NSLock property, called lock:

@property (nonatomic, strong) NSLock *lock; 

您是在启动线程测试之前创建的:

Which you created before initiating your thread test:

- (void) threadTest { size = 0; self.lock = [[NSLock alloc] init]; NSThread* T1 = [[NSThread alloc] initWithTarget:self selector:@selector(workerThread:) object:@"T1"]; [T1 start]; NSThread* T2 = [[NSThread alloc] initWithTarget:self selector:@selector(workerThread:) object:@"T2"]; [T2 start]; NSThread* T3 = [[NSThread alloc] initWithTarget:self selector:@selector(workerThread:) object:@"T3"]; [T3 start]; } 

已经说完了,您首先从将控制返回到主线程"开始.正如我之前所说,确实没有必要这样做,因为在您的示例中,应用程序的主线程从未产生控制权

Having said all this, you started this with "return control back to the main thread". As I said earlier, there's really no need to do that because in your example, your app's main thread never yielded control

对于控制发生在不同线程上的任务之间的关系,我建议使用GCD或操作队列.它们更易于使用,并且具有更好的机制来控制各种任务/操作之间的依赖关系(请参见

For controlling relationships between tasks happening on different threads, I might suggest using GCD or operation queues. They're easier to use and have better mechanism for controlling dependencies between various tasks/operations (see Concurrency Programming Guide).

例如,考虑与上述workerThread方法相同的基于操作的方法(相同,但不需要自动释放池):

For example, consider the operation-based equivalent to your above workerThread method (identical, but no autorelease pool is needed):

- (void) operationMethod:(id)obj { BOOL done = NO; while (!done) { [self.lock lock]; if (size < 9) { size++; NSLog(@"Operation:%@--------Size:%d", obj, size); } else { done = YES; } [self.lock unlock]; // perhaps you're doing something time consuming here... } } 

然后您可以创建三个操作(可能将在三个线程上运行)并等待结果,如下所示:

You could then create three operations (which probably will run on three threads) and wait for the result, like so:

- (void) operationTestWait { size = 0; self.lock = [[NSLock alloc] init]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; NSOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationMethod:) object:@"Op1"]; NSOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationMethod:) object:@"Op2"]; NSOperation *op3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationMethod:) object:@"Op3"]; [queue addOperations:@[op1, op2, op3] waitUntilFinished:YES]; // do here whatever should happen when the operations are done } 

在这种情况下,主线程将等待这三个操作完成.

In this case, the main thread will wait for these three operations to finish.

或者,更好的是,如果这些任务花费了几毫秒的时间,则您不应该等待主队列(因为您应该从不阻塞主队列),而是应该简单地定义完成这三个操作后,您希望主队列执行的操作:

Or, better, if these tasks take more than a few milliseconds, you should not have the main queue wait (since you should never block the main queue), but rather, you should simply define what you want the main queue to do when the three operations are done:

- (void) operationTest { size = 0; self.lock = [[NSLock alloc] init]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; NSOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationMethod:) object:@"Op1"]; NSOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationMethod:) object:@"Op2"]; NSOperation *op3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationMethod:) object:@"Op3"]; NSOperation *completion = [NSBlockOperation blockOperationWithBlock:^{ // if you want this to do something on the main queue, then have this add it to the main queue [[NSOperationQueue mainQueue] addOperationWithBlock:^{ // do here whatever should happen when the operations are done }]; }]; // define this completion operation to be dependent upon the above three operations [completion addDependency:op1]; [completion addDependency:op2]; [completion addDependency:op3]; // now add all of them, but don't wait until finished; // but the completion operation will only start when its dependencies // are resolved [queue addOperations:@[op1, op2, op3, completion] waitUntilFinished:NO]; } 

请原谅冗长的答案.如果您可以为我们提供这些线程将要执行的操作的更实际示例,并且我们可以为如何最好地解决该问题提供更好的建议.但是,通常来说,操作队列或调度队列可能是解决大多数并发相关挑战的更有效方法.

Forgive the long-winded answer. If you can give us a more practical example of what these various threads will be doing and we can provide better counsel on how to best tackle it. But, in general, operation queues or dispatch queues will probably be more efficient way to tackle most concurrency related challenges.

这篇关于多个NSThreads同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程技术网(www.editcode.net)!

腾讯云服务器 阿里云服务器
关注微信
^