3
我有一個ObjC類(Writer),它具有一些屬性,並將它寫入主線程的這些屬性。然後有另一個類(Reader)讀取主線程或後臺線程中的這些屬性。ObjectiveC在讀取發生時鎖定寫入操作
當讀者從主線程讀取時,它會得到Writer類中這些屬性的確切值,但是當讀者從後臺線程讀取時,顯然沒有保證讀取器會得到相同的值。這是示例代碼。
在這裏,在Writer類
- numberString是一個逗號,前分開的所有的人。 1,1,1,1
- numberSum是這些的總和,例如。 4
在Reader類:
我想確保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中的兩個NSLog語句在主線程中執行時總是打印相同的數據,但在後臺線程中它們會有所不同,例如在讀取數字字符串之後讀取數字字符串中的數字字符串,它已由Writer中的主線程更新。
我應該怎麼做才能確保我總能得到正確的值而不考慮調用線程?
感謝您提醒我dispatch_barrier。有一件事情,它適用於一個或兩個變量,但如果你想要在不同類別中散佈的相當多的變量,那該怎麼辦。我們仍然遵循相同的方法,或者我們可以有任何其他解決方案,而不需要在不同的課程中做同樣的事情? –
你可以考慮任何適用於你的案例的方法。然而,總體思路是同步訪問節,其中可能存在競爭條件。因此,如果您的資源分散在不同的類中,請考慮創建一個對象,以便您訪問所有其他對象並進行所有同步。看看外觀模式 –