线程安全中应该注意的点

何谓线程安全?


在《java 并发编程实践》中对线程安全的定义如下:

当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替运行,并且不需要额外的同步及在调用方代码不必做其他的协调,这个类的行为仍然是正确的,那么这个类就是线程安全的。

很多时候,在单线程环境下很稳定的程序,到了多线程环境下,往往就变得不安全了。

1. 完全由线程安全的类构成的程序不一定就是线程安全的。
如下代码所示:
Vector v;
 
if(!v.contains(o)){
v.add(o);
}

虽然Vector是一个线程安全的类,但是对于由Vector线程安全的方法组成上面的逻辑,显然不是线程安全的

当然,由线程不安全的类构成的程序,也不一定不是线程安全的。

2. 多线程环境下,直觉有时候不准。
当变量的读入写出被不同的线程共享时,必须使用同步。若不使用同步将有可能发生与直觉大相径庭的错误。
public class TestVisiable {
static int x=0,y=0;
static int b=0,a=0;

public static void main(String[] args) throws InterruptedException {
          Thread t1 = new Thread(new Runnable(){
           public void run(){
                a=1;
                x=b;
            }
          });
         Thread t2 = new Thread(new Runnable(){
          public void run(){
                b=1;
                y=a;
            }
          });
        t1.start();       t2.start();
        t1.join();        t2.join();
       System.out.println(x+" "+y);
  }
}
由于没有同步,程序运行的可能结果为(1,0) (0,1),(1,1),然而,还有可能为(0,0),不可思议吧,这是由于为了加快并发执行,JVM内部采用了重排序的机制导致。

3. 简单类型中的特殊类型
在java中,java存储模型要求java变量的获取和存储都是原子操作,但是有两种类型的变量是比较特殊的
没有申明为volitale 的long和double变量
原因在于,在java中long和double变量为64位,jvm允许将64位的读写操作划分为两个32位的操作。当多个线程同时读写非volatile的long或者double类型数据时,将有可能得到数据是一个数的高32位和另一个数的低32位组成的数。这样的结果显然是完全不对的。因此对应long或double类型的数据用于多线程共享时,必须申明加上volatile或者进行同步。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值