我Future
在 Objective-C 中实现了一个类,类似于 Java 的java.util.concurrent.Future
,但更适合我的简单需求。这是实现:
typedef id (^TaskBlock)();
static int NotDone = 0;
static int Done = 1;
@implementation Future
- (id)initWithBlock:(TaskBlock)aBlock {
if((self = [super init])) {
lock = [[NSConditionLock alloc] initWithCondition:NotDone];
block = aBlock;
}
return self;
}
- (void)set:(id)aValue {
if ([lock tryLockWhenCondition:NotDone]) {
[lock lockWhenCondition:NotDone];
value = aValue;
[lock unlockWithCondition:Done];
}
}
- (id)get {
DLog(@"Retrieving future value");
[lock lockWhenCondition:Done];
id v = value;
[lock unlock];
return v;
}
- (void)start {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
DLog(@"Requesting future value");
[self set:block()];
DLog(@"Future value set");
});
}
@end
当我使用它时,一个线程首先get:
像这样被阻塞(它等待由 表示的冗长计算block
完成):
frame #0: 0x9139783e libsystem_kernel.dylib`__psynch_cvwait + 10
frame #1: 0x904a4e78 libsystem_c.dylib`_pthread_cond_wait + 914
frame #2: 0x904a4f7b libsystem_c.dylib`pthread_cond_timedwait_relative_np + 47
frame #3: 0x00b565f2 Foundation`-[NSCondition waitUntilDate:] + 389
frame #4: 0x00b26fc0 Foundation`-[NSConditionLock lockWhenCondition:beforeDate:] + 285
frame #5: 0x00b26e9d Foundation`-[NSConditionLock lockWhenCondition:] + 69
frame #6: 0x0000c335 Jungle`-[Future get](self=0x0757e220, _cmd=0x0000ec3a) + 85 at Future.m:52
frame #7: 0x0000ab23 Jungle`-[GADelayedBinding waitDelayed](self=0x071c39e0, _cmd=0x0000eb1d) + 99 at GADelayedBinding.m:44
frame #8: 0x00007a26 Jungle`-[GATuple waitDelayed](self=0x071baa70, _cmd=0x0000eb1d) + 390 at GATuple.m:99
frame #9: 0x000098fa Jungle`-[GAUnifier unify:with:dynamicContext:](self=0x07561030, _cmd=0x0000eaf8, query=0x071bcc50, base=0x07182f40, dynamicContext=0x00000000) + 2442 at GAUnifier.m:85
frame #10: 0x00009b06 Jungle`-[GAUnifier unify:with:](self=0x07561030, _cmd=0x0000e71e, query=0x071bcc50, base=0x07182f40) + 118 at GAUnifier.m:93
frame #11: 0x00002b44 Jungle`__32-[ViewController viewDidAppear:]_block_invoke(.block_descriptor=0x0756a6a0) + 84 at ViewController.m:38
frame #12: 0x04a0a53f libdispatch.dylib`_dispatch_call_block_and_release + 15
frame #13: 0x04a1c014 libdispatch.dylib`_dispatch_client_callout + 14
frame #14: 0x04a0d2e8 libdispatch.dylib`_dispatch_root_queue_drain + 335
frame #15: 0x04a0cfcb libdispatch.dylib`_dispatch_worker_thread3 + 20
frame #16: 0x904a2b24 libsystem_c.dylib`_pthread_wqthread + 346
计算完成后,我在此处收到有关死锁的错误:
frame #0: 0x00b9f80f Foundation`_NSLockError
frame #1: 0x00b26f6f Foundation`-[NSConditionLock lockWhenCondition:beforeDate:] + 204
frame #2: 0x00b26e9d Foundation`-[NSConditionLock lockWhenCondition:] + 69
frame #3: 0x0000c268 Jungle`-[Future set:](self=0x0757e220, _cmd=0x0000ec35, aValue=0x07578b40) + 136 at Future.m:43
frame #4: 0x0000c501 Jungle`__15-[Future start]_block_invoke(.block_descriptor=0x0757e330) + 113 at Future.m:63
frame #5: 0x04a0a53f libdispatch.dylib`_dispatch_call_block_and_release + 15
frame #6: 0x04a1c014 libdispatch.dylib`_dispatch_client_callout + 14
frame #7: 0x04a0d2e8 libdispatch.dylib`_dispatch_root_queue_drain + 335
frame #8: 0x04a0cfcb libdispatch.dylib`_dispatch_worker_thread3 + 20
frame #9: 0x904a2b24 libsystem_c.dylib`_pthread_wqthread + 346
我做错了什么?我的锁正在等待的所有条件对我来说都是正确的。