1

FutureJava の に似た Objective-C でクラスを実装して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

私がそれを使用しているとき、1 つのスレッドが最初に次の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:は、成功すると実際にロックを取得するため、2 回ロックしようとするとデッドロックが発生します。

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

また、あなたがしようとしていることは、指定しない場合のプロパティのデフォルトの動作であることも指摘したいと思いますnonatomic

于 2013-03-27T20:52:03.220 に答える