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。有一件事情,它适用于一个或两个变量,但如果你想要在不同类别中散布的相当多的变量,那该怎么办。我们仍然遵循相同的方法,或者我们可以有任何其他解决方案,而不需要在不同的课程中做同样的事情? –
你可以考虑任何适用于你的案例的方法。然而,总体思路是同步访问节,其中可能存在竞争条件。因此,如果您的资源分散在不同的类中,请考虑创建一个对象,以便您访问所有其他对象并进行所有同步。看看外观模式 –