线程安全型与非安全型的数值序列生成器

线程安全性可能是非常复杂的,在没有充足同步的情况下,多个线程中的操作执行顺序是不看预测的,甚至会产生奇怪的效果。

package com.aj.UnsafeAndSafeSequence;

public class UnsafeSequence {
    private int value;

    //返回一个唯一的数值
    public int getNext(){
        return value++;
    }
}
其实我们表明上看,这个程序是没什么问题的,但是如果执行时机不对,这两个线程在调用getNext时候,会得到相同的值。因为此操作包含了三个独立的子操作:
1. 读取value值
2. 将value值加1
3. 并将结果值计算写入value中
其结果就是,在不同线程的调用中返回了相同的数值,由于存在指令重排序的可能,因此实际情况可能会更加的糟糕。



图1-1 不同线程之间的一种交替执行的情况
UnsafeSequence是一种常见的并发安全问题,简称竞态条件。在多线程环境下,getValue是否会返回唯一的值,要取决于运行时对线程中操作的交替执行方式,这并不是我们希望看到的。由于多线程要共享相同的内存地址空间,并且是并发运行,因此它们可能会访问或者修改其他线程正在修改的变量。这样的好处是:更容易实现数据共享。坏处是:线程会由于无法预料的数据变化而发生错误。
将上面的UnsafeSequence程序中的getNext修改为一个同步方法,可以修复错误。具体如下面程序:

package com.aj.UnsafeAndSafeSequence;

public class SafeSequence {
   private int value;
   public synchronized int getNext(){
       return value++;
   }
}

如果没有同步,无论是编译器、硬件还是运行时,都可以随意安排操作的顺序和执行时间。开发人员必须找出这些数据在哪些位置被多个线程共享,这样才能使这些优化措施不破坏线程安全性。

参考《Java Concurrency in Practice》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值