这是我在方法中所拥有的伪代码:
NSCondition condition = [[NSCondition alloc] init];
int predicate = 0;
dispatch_sync(dispatch_get_main_queue(), ^
{
[condition lock]; // Lock-0
});
bindBlock1ForDataReceived(^()
{
// Not main thread here.
// Get on main thread, because lock and unlock must be run on same thread.
dispatch_sync(dispatch_get_main_queue(), ^
{
predicate = 1;
[condition signal];
[condition unlock]; <<<<---- "unlocked when not locked"
});
});
bindBlock2ForNoDataAvailable(^()
{
// Not main thread here.
// Get on main thread, because lock and unlock must be run on same thread.
dispatch_sync(dispatch_get_main_queue(), ^
{
predicate = 2;
[condition signal];
[condition unlock];
});
});
[condition lock]; // Lock-1
while (predicate == 0)
{
[condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]];
}
[condition unlock];
if (predicate == 2)
{
[condition lock]; // Lock-2
[condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
[condition unlock];
}
问题是,当第一个事件2发生,然后是事件1时,我从iOS(见上文)获得“未锁定时解锁”警告。
现在让我解释一下我要完成的任务:这是数据获取器的一部分。接收正常情况数据并执行block1:没有问题。有时,无数据块2首先被虚假执行,紧接着是block1;这是我收到NSCondition
警告的时候。为了抓住这种罕见的情况,我等待2.0
秒。这是发生的事情:
predicate
不再是0
所以没有等待。if
为真的(predicate == 2)
语句。2.0
秒。根本原因(见上文)是方法(工人/消费者)获取锁,而数据生产者应该获取锁。我花了很多时间试图解决这个问题;我的一个想法是使用两个NSCondition
,但我无法弄明白,因为事情是相互交织的。
注意:我发现警告没有出现在unlock
声明中的if
,这很奇怪。
谢谢你的时间!
答案 0 :(得分:1)
使用
的最简单方法是使用dispatch_group_t confirmGroup = dispatch_group_create(); // 1
if (requestContacts) {
dispatch_group_enter(confirmGroup); // 2
[Extractor requestAccessAddressBook:^(BOOL isComplete) {
if (isComplete) {
dispatch_group_leave(confirmGroup); //2
}
}];
}
if (requestEvent) {
dispatch_group_enter(confirmGroup); // 3
[Extractor requestAccessEvents:^(BOOL isComplete) {
if (isComplete) {
dispatch_group_leave(confirmGroup); // 3
}
}];
}
if (requestPhoto) {
dispatch_group_enter(confirmGroup); // 4
[Extractor requestAccessPhotos:^(BOOL isComplete) {
if (isComplete) {
dispatch_group_leave(confirmGroup); //4
}
}];
}
NSLog(@"dispatch_group_wait confirmations");
dispatch_group_wait(confirmGroup, DISPATCH_TIME_FOREVER); // 5