をデッドロック:dispatch_barrier_syncは、常に次のコードスニペットを考える
#import <XCTest/XCTest.h>
@interface DispatchTests : XCTestCase {
dispatch_queue_t _workQueue;
dispatch_queue_t _readWriteQueue;
int _value;
}
-(void)read;
-(void)write;
@end
@implementation DispatchTests
-(void)testDispatch {
_workQueue = dispatch_queue_create("com.work", DISPATCH_QUEUE_CONCURRENT);
_readWriteQueue = dispatch_queue_create("com.readwrite", DISPATCH_QUEUE_CONCURRENT);
_value = 0;
for(int i = 0; i < 100; i++) {
dispatch_async(_workQueue, ^{
if(arc4random() % 4 == 0) {
[self write];
} else {
[self read];
}
});
}
XCTestExpectation* expectation = [self expectationWithDescription:@"dude"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:6.0 handler:nil];
}
-(void)read {
dispatch_sync(_readWriteQueue, ^{
NSLog(@"read:%d", _value);
});
}
-(void)write {
dispatch_barrier_sync(_readWriteQueue, ^{
_value++;
NSLog(@"write:%d", _value);
});
}
@end
この試験の目的は、私は、読み取り/書き込みロックを管理するためにdispatch_barrier
を使用できるかどうかを確認することです。このテストでは、リーダーとライターの両方が同期しています。私がバリアを非同期にすると、テストはうまくいくように見えますが、非同期動作を避けたいのですが、この実装は簡単ではないためです。
私はwrite
メソッドがデッドロックしている理由を理解しようとしています。
バリアブロックがプライベートコンカレント キューの前面に到達するとすぐには実行されません。代わりに、キューは、現在実行中のブロックの実行が終了するまで まで待機します。その時点で、 キューはバリアブロックを単独で実行します。 の後に提出されたブロックは、バリアブロックが完了するまで実行されません。
「現在実行中のブロック」が意味するものとは混同しています。
マイ解釈の束(x)は書き込み(Y)、次に、送信取得読み出し、このシナリオでは、より多くの(Z)を読み出す:
- (X)
- (y)を実行します待機(X)
- の実行から
- (Y)ブロック(z)が行われる(X)
- を完了するには(Y)
- (y)を実行 を完了するまで - 理論的にはあなたのコードではなくブロックを行います。
- (z)は
- (z)を実行し、実際のテストの後、それは、
私はサンプルをテストしていませんが、見てから、デッドロックする必要はありません、IMHO。 – CouchDeveloper