__block NSHTTPURLResponse *httpResponse;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error)
httpResponse = (NSHTTPURLResponse *)response;
}
dispatch_semaphore_signal(semaphore);
}];
[task resume];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
在此之后阅读httpResponse
是否安全?信号量等待块执行竞争。如果没有错误,是否会立即看到作业,还是必须在块外同步或创建内存屏障?
等待信号量是否隐式执行某些同步,这使得__block变量可以立即读取。如果用Java中的Thread.join()
而不是信号量来完成,那么它将是安全的,因为它保证了与"块"中的赋值之间发生的关系。
答案 0 :(得分:0)
简短的回答是肯定的。
信号量锁实际上会强制当前运行的线程停止执行,直到它收到足够的解锁信号才能继续。
在允许信号量继续执行之前,在其他某个线程上修改了您定义的变量,因此您的分配应该安全地进行。
答案 1 :(得分:0)
似乎dispatch_semaphore_wait
也是一个内存屏障,因此可以安全地读取该值。
答案 2 :(得分:0)
严格地说,此代码将阻止执行线程(可能是主线程),直到发出信号量锁信号。所以 - 简短的回答,是的它应该有效,但这不是最佳实践,因为它阻止了主线程。
更长的答案:
是的,信号量将确保__block捕获的存储在被填充之前不被访问。但是,调用线程将被等待阻塞直到块完成。这不是理想的 - 正常的UI任务,如确保活动指标旋转不会发生。
最佳做法是在块完成后让块信号成为主要对象(可能使用对主队列的dispatch_async调用),之后仅访问它。特别是如果您的会话任务失败(例如,来自网络连接),则调用线程可能会阻塞,直到调用完成处理程序并出现超时错误。这对应用程序来说似乎已经冻结,并且他们无法对此做任何事情,但会杀死该应用程序。
有关使用块的更多信息,请参阅:
特别针对数据会话任务的最佳实践: