プロパティを持つObjCクラス(Writer)があり、メインスレッドのこれらのプロパティに書き込みます。次に、メインスレッドまたはバックグラウンドスレッドでこれらのプロパティを読み取る他のクラス(Reader)があります。ObjectiveCは読み取り時に書き込み操作を実行します
リーダーがメインスレッドから読み取るとき、Writerクラスのこれらのプロパティが保持する正確な値を取得しますが、リーダーがバックグラウンドスレッドから読み取るときには、明らかに同じ値を保証する保証はありません。ここに例のコードを示します。
ここライター・クラスの
- numberStringは、カンマで区切られたすべてのもの、例です。 1,1,1,1
- numberSumはこれらの合計です。リーダークラスで4
:
私はnumberSumが実際に numberString変数内のすべてのものの和であることを確認します。
// Writer Class
@interface Writer : NSObject
@property (nonatomic,strong) NSString* numberString;
@property (nonatomic,assign) NSUInteger numberSum;
@end
@implementation Writer
-(instancetype)init {
if (self = [super init]){
self.numberString = @"1";
self.numberSum = 1;
self.timer = [NSTimer timerWithTimeInterval:0.1f target:self selector:@selector(writeToVariables:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
return self;
}
- (void)writeToVariables:(NSTimer *)timer {
self.numberString = [self.numberString stringByAppendingString:@",1"];
self.numberSum += 1;
}
// Reader Class
@interface Reader()
@property (nonatomic,strong) Writer* writer;
@end
@implementation Reader
-(instancetype)init {
if (self = [super init]){
self.writer = [Writer new];
}
return self;
}
-(void) getVariablesOnBackground:(BOOL)background {
void (^readerBlock)() = ^{
NSString* numberStr = self.writer.numberString;
// Introduce delay So background thread get time to update numberSum
int i=0;
while (i < 10000000) {
i += 1;
}
NSUInteger numberSum = self.writer.numberSum;
NSArray *onesArray = [numberStr componentsSeparatedByString:@","];
NSLog(@"%lu",(unsigned long)onesArray.count);
NSLog(@"%lu",(unsigned long)numberSum);
};
// If background then dispatch on default queue else just call the block
if (background) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),readerBlock);
}
else {
readerBlock();
}
}
@end
これは単なる例示のためのデモコードです。 readerBlock内の2つのNSLogステートメントは、メインスレッドで実行されたときに常に同じものが印刷されますが、バックグラウンドスレッドでは、WriterのメインスレッドによってnumStringが読み取られた後、Readerで読み取られるtimeSumによって時間が異なります。
呼び出しスレッドに関係なく常に正しい値を取得するにはどうすればよいですか?
私はdispatch_barrierを思い出してくれてありがとう。しかし、1つまたは2つの変数ではうまくいきますが、異なるクラスに分散したかなりの変数で同じものを使用したい場合はどうすればよいでしょうか。私たちはまだ同じアプローチに従っていますか、あるいは別のクラスで同じことをしなくても、他の解決策をとることはできますか? –
あなたのケースではうまくいくようなアプローチが考えられます。しかし、一般的な考え方は、競合状態が可能なセクションへのアクセスを同期させることです。したがって、クラスに分散するリソースがほとんどない場合は、他のすべてのクラスにアクセスし、すべての同期を行うオブジェクトを作成することを検討してください。ファサードのパターンを見てください –