几个想法:
您说“当 size=10 时将控制权返回给主线程”。这不太合理。主线程永远不会“失去”控制权(因为这些线程是同时发生的)。当这种情况出现时,也许您希望在主线程上发生一些事情?
您没有让该workerThread
方法执行任何循环,因此在您编写它时,每个线程都会执行一次然后退出。您可能需要在此处添加某种形式的循环。
即使您添加了循环,您想要的输出也表明您正在假设将发生的特定操作序列,即这三个线程将按顺序运行(但您没有这样的保证)。如果您需要这种行为,您可以设置一系列信号量,通过这些信号量,您可以让一个线程等待另一个线程发送信号。
从不同线程更新变量时应该小心。请参阅线程编程指南的同步部分。在处理像您的计数器这样的基本数据类型时,它被简化了(只需确保将其声明为)。但在更实质性的场景中,您将需要使用一些同步技术,例如锁、专用自定义串行队列等。atomic
@synchronized
一般来说,如果您使用线程(但如果使用队列则没有必要),您应该为您的线程创建一个自动释放池。
无论如何,除了这些观察之外,您可能会有以下内容,其中 (a) 有@autoreleasepool
; (b) 循环;(c) 使用锁来确保各个线程同步它们与size
变量的交互:
- (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;
您在启动线程测试之前创建的:
- (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];
}
说了这么多,您从“将控制权返回给主线程”开始。正如我之前所说,实际上没有必要这样做,因为在您的示例中,您的应用程序的主线程从未产生控制权
为了控制不同线程上发生的任务之间的关系,我可能建议使用 GCD 或操作队列。它们更易于使用,并且具有更好的机制来控制各种任务/操作之间的依赖关系(请参阅并发编程指南)。
例如,考虑与上述方法等效的基于操作的workerThread
方法(相同,但不需要自动释放池):
- (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...
}
}
然后,您可以创建三个操作(可能会在三个线程上运行)并等待结果,如下所示:
- (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];
}
原谅冗长的答案。如果你能给我们一个更实际的例子来说明这些不同的线程将做什么,我们可以就如何最好地解决它提供更好的建议。但是,一般来说,操作队列或调度队列可能是解决大多数并发相关挑战的更有效方式。