iOS 属性修饰符atomic并不是绝对安全的

    atomic原子性,是否是绝对线程安全的,不是绝对线程安全怎么理解?首先看一下代码以及打印结果

@property (atomic, assign) NSInteger intA;   //有一个atomic的属性,表示是原子的


- (void)viewDidLoad {
   [super viewDidLoad];
   //开启一个线程对intA的值+1
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       for (int i = 0;i < 1000;i ++){
           self.intA = self.intA + 1;
       }
       NSLog(@"intA : %ld",(long)self.intA);
   });
   
   //开启一个线程对intA的值+1
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       for (int i = 0;i < 1000;i ++){
           self.intA = self.intA + 1;
       }
       NSLog(@"intA : %ld",(long)self.intA);
   });   
}

   错误的分析是:因为intA是atomic修饰的,所以是线程安全的,在+1的时候,只会有一个线程去操作,所以最终的打印结果必定有一个是2000。

    看一下打印结果

2018-09-12 08:47:20.019123+0800 Test[1019:48584] intA : 1186
2018-09-12 08:47:20.019123+0800 Test[1019:48583] intA : 896

  最终的结果和我们预期的完全是不一样的,这是为什么呢?

  注意

        其实atomic是原子的是没问题的,这个只是表示set方法是原子的,效果是类似于下面的效果

//atomic表示的是对set方法加锁,表示在设置值的时候,只会有一个线程执行set方法
- (void)setIntA:(NSInteger)intA{
    [self.lock lock];
    _intA = intA;
    [self.lock unlock];
}

   只是对set方法加锁,而我们程序里面的self.intA = self.intA + 1; 这一部分不是线程安全的,后面这个+1操作不是线程安全的,所以要想最终得到2000的结果,需要使用锁对self.intA = self.intA + 1加锁,代码如下,这里可以将atomic修饰词改为nonatomic,最终修改的代码以及打印结果如下:

@property (nonatomic, assign) NSInteger intA;
- (void)viewDidLoad {
    [super viewDidLoad];
    self.lock = [[NSLock alloc] init];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i = 0;i < 1000;i ++){
            [self.lock lock];
            self.intA = self.intA + 1;
            [self.lock unlock];
        }
        NSLog(@"intA : %ld",(long)self.intA);
    });

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i = 0;i < 1000;i ++){
            [self.lock lock];
            self.intA = self.intA + 1;
            [self.lock unlock];
        }
        NSLog(@"intA : %ld",(long)self.intA);
    });
 }


打印结果
2018-09-12 09:06:57.071829+0800 Test[2200:97290] intA : 1360
2018-09-12 09:06:57.071966+0800 Test[2200:97293] intA : 2000

  至于使用哪种锁,自己选择吧,不同的锁有不同的执行效率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值