多NSThreads同步
我想要实现使用NSThread
多NSThreads同步
我有一个主线程和三(3)的WorkerThread T1,T2,T3以下任务。所有这些从主线程同时开始,主线程有一个int size
变量。现在我想在某种程度上,他们三个同步线程,当我的上述每个线程将执行,它将打印如下:
//在主线程
- (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
并返回控制权交还给麦n个线程时size=10
一对夫妇的想法:
你说 “控制权返回给主线程时大小= 10”。这不太合理。主线程永远不会“失控”(因为这些线程同时发生)。也许你想在这种情况发生时在主线上发生什么事情?
你没有
workerThread
方法做任何循环,因此,如你所写,每个线程都会这样做,然后退出。您可能需要在此添加某种形式的循环。即使您添加了循环,您希望的输出表明您正在假设将发生的特定操作序列,即这三个线程将按顺序运行(但您没有这样的保证)。如果你需要这种行为,你会建立一系列的信号灯,通过它你可以让一个线程等待一个信号被另一个线程发送。
从不同线程更新变量时应该小心。请参阅“线程编程指南”的Synchronization部分。处理像您的计数器这样的基本数据类型时会简化(只需确保将其声明为
atomic
)。但在更实质性的情况下,您会想要采用一些同步技术,例如@synchronized
,锁定,专用定制串行队列等。通常,如果您使用的是线程(但如果使用队列则不需要) ,你的线程应该是creating an autorelease pool。
无论如何,与这些观察之外,你可能会有诸如以下,其中(一)具有@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];
}
说完所有这些之后,你就开始使用“return control back to the主线程“。正如我前面所说,真的没有必要这样做,因为在你的例子中,你的应用程序的主线程永远不会控制
为了控制在不同线程上发生的任务之间的关系,我可能会建议使用GCD或操作队列。它们更易于使用,并具有更好的机制来控制各种任务/操作之间的依赖关系(请参阅Concurrency Programming Guide)。
例如,考虑基于操作相当于你上面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];
}
原谅啰嗦的答案。如果你能给我们一个更实际的例子,说明这些各种线索将会做什么,我们可以就如何最好地解决它提供更好的建议。但是,一般来说,操作队列或调度队列可能会更有效地解决大多数并发相关的挑战。
您明确使用线程而不是GCD或NSOperationQueues的任何特定原因? – JonahGabriel