多个NSThreads同步

我想用NSThread来实现以下任务

我有一个主线程和三(3)workerThread T1,T2,T3。 所有这些从主线程同时开始,主线程有一个int sizevariables。 现在我想以一种方式同步所有三个线程,当我的每个线程都执行时,它将打印出下列内容:

//在主线程中

 - (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. 你说“大小= 10时,将控制权归还给主线程”。 这不太合理。 主线程永远不会“失去”控制(因为这些线程同时发生)。 当这种情况出现时,也许你想在主线上发生什么?

  2. 你没有workerThread方法做任何循环,所以你写了它,每个线程会做一次,然后退出。 你可能需要在这里添加一些forms的循环。

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

  4. 更新来自不同线程的variables时应该小心。 请参阅“ 线程编程指南”的“ 同步”部分 处理像计数器这样的基本数据types时简化(只要确保将其声明为atomic )。 但在更实质性的情况下,你会想要使用一些同步技术,如@synchronized ,locking,专用的自定义串行队列等。

  5. 一般来说,如果你正在使用线程(但如果使用队列则不需要),你应该为你的线程创build一个自动释放池 。

无论如何,除了这些意见之外,你可能有类似以下的事情,(a)有@autoreleasepool ; (b)循环; 和(c)使用一个锁来确保各个线程与sizevariables同步它们的交互:

 - (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... } } } 

这假定你有NSLock属性,叫lock

 @property (nonatomic, strong) NSLock *lock; 

在启动线程testing之前创build的是:

 - (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]; } 

说完这一切,你开始了这个“返回控制回主线程”。 正如我刚才所说,真的没有必要这样做,因为在你的例子中,你的应用程序的主线程从来没有得到控制

为了控制在不同线程上发生的任务之间的关系,我可能会build议使用GCD或操作队列。 它们更易于使用,并具有更好的机制来控制各种任务/操作之间的依赖关系(请参见并发编程指南 )。

例如,考虑基于操作的等同于上面的workerThread方法(相同,但不需要autorelease池):

 - (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... } } 

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

 - (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 } 

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

或者更好的是,如果这些任务花费的时间超过了几个毫秒,那么你不应该等待主队列(因为你不应该阻塞主队列),而应该简单地定义主队列要做什么。三个操作完成:

 - (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]; } 

原谅啰嗦的回答。 如果你能给我们一个更实际的例子,说明这些各种线索将会做什么,我们可以就如何最好地解决这个问题提供更好的build议。 但是,一般来说,操作队列或调度队列可能会更有效地解决大多数并发相关的挑战。