0

I'm in a situation where I want to ensure two queues end up executing on different threads. Ideally, I'd like to ensure they're serial queues. In particular, in the example below, if both queues run on the same thread, doStuff will be busy-waiting indefinitely. Am I going to have to move to explicit threading or can I salvage use of GCD here?

- (void)foo {
    self.responseQueue = dispatch_queue_create("com.blah.response", DISPATCH_QUEUE_SERIAL);

    self.requestQueue = dispatch_queue_create("com.blah.request", DISPATCH_QUEUE_SERIAL);

    dispatch_async(self.requestQueue, ^{
        [self doStuff];
    });
}

- (BOOL)doStuff {
    BOOL __block waiting = YES;

    self.responseBlock = ^{
        waiting = NO;
    };

    [self performRequest];

     while (waiting) {
         // realize could use dispatch_semaphore (busy waiting just to illustrate point).    
         sleep(1);
     }

     [self doStuffRequiringResponseCompletion];

     // I realize it would be sensible to 
     // 1) Not block in the above while loop.
     // 2) Call |doStuffRequiringResponseCompletion| after |receivedResponse|.
     // I don't want to do this.
}

// method called on arbitrary thread
- (void)receivedResponse {
    // stuff

    dispatch_async(self.responseQueue, self.responseBlock);
}

See also: Is there any reason to not use sleep in a Grand Central Dispatch queue??

4

4 回答 4

1

您不能确保它们在不同的线程上运行——调度队列的重点是操作系统为您管理线程。但是,除非您正在做一些真正需要在特定线程上运行的高度专业化的工作,否则串行调度队列的默认行为应该对您非常有用。如果您确实需要确保特定线程,那么您将重新使用 NSThread。

于 2013-07-15T23:52:45.460 回答
1

调度队列不绑定到线程。如果您的调度项之一阻塞了线程,GCD 将使用或创建其他线程来处理其他队列(以及此队列中的其他项,如果它是并发队列)。

GCD 将创建的线程数有上限。如果您有太多像这样休眠的调度项,那么您可能会遇到该限制并可能出现死锁。

于 2013-07-16T20:42:53.163 回答
0

您应该避免阻塞线程。使用您的示例,在您的响应块中,处理响应后,您可以将另一个块排入 com.blah.request 以执行您正在等待执行的任何操作。

于 2013-07-16T00:04:58.437 回答
0

我不建议使用这个解决方案,因为调度队列不应该被滥用于同步目的,但我所追求的是这样的(但是这不能保证不会死锁——如果 dispatch_sync 块在不同的线程上运行,可能会发生死锁由 performSelectorInBackground 旋转的那个):

- (void)foo {
    self.responseQueue = dispatch_queue_create("com.blah.response", DISPATCH_QUEUE_SERIAL);

    self.requestQueue = dispatch_queue_create("com.blah.request", DISPATCH_QUEUE_SERIAL);

    [self performSelectorInBackground:@selector(dispatchRequest) withObject:nil]
}

- (void)dispatchRequest {
    dispatch_sync(self.requestQueue, ^{
        [self doStuff];
    });
}
于 2013-07-16T01:29:29.820 回答