1

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

我做错了什么?我的锁正在等待的所有条件对我来说都是正确的。

4

1 回答 1

2

该方法tryLockWhenCondition:在成功时实际上会获取锁,因此您尝试将其锁定两次,这会导致死锁。

if ([lock tryLockWhenCondition:NotDone]) {
    [lock lockWhenCondition:NotDone]; //Remove this

我还想指出,当您未指定nonatomic.

于 2013-03-27T20:52:03.220 回答