gpt4 book ai didi

ios - 多个 NSThreads 同步

转载 作者:塔克拉玛干 更新时间:2023-11-02 10:08:16 24 4
gpt4 key购买 nike

我想使用 NSThread 实现以下任务

我有一个主线程和三 (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

size=10

时,将控制返回给主线程

最佳答案

几个想法:

  1. 您说“当 size=10 时将控制返回给主线程”。这不太合理。主线程永远不会“失去”控制(因为这些线程是同时发生的)。也许您希望在出现这种情况时在主线程上发生一些事情?

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

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

  4. 从不同的线程更新变量时应该小心。查看Synchronization Threading Programming Guide 的部分。 在处理像计数器这样的基本数据类型时,它得到了简化(只需确保将其声明为 atomic)。但在更实质性的场景中,您需要使用一些同步技术,例如 @synchronized、锁、专用自定义串行队列等。

  5. 一般来说,如果您正在使用线程(但如果使用队列则不是必需的),您应该是 creating an autorelease pool为你的主题。

无论如何,撇开这些观察不谈,您可能会得到类似下面的东西,其中 (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 或操作队列。它们更易于使用并且具有更好的机制来控制各种任务/操作之间的依赖关系(参见 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];
}

原谅冗长的回答。如果你能给我们一个更实际的例子,说明这些不同的线程将做什么,我们就可以就如何最好地解决它提供更好的建议。但是,一般来说,操作队列或调度队列可能是解决大多数并发相关挑战的更有效方法。

关于ios - 多个 NSThreads 同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19284249/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com