java多线程为什么多行赋值是不安全的?

多线程中为了提高执行效率,不需要synchronized的操作,同时保证原子性。

JVM规范定义了几种原子操作:

1、基本类型(long和double除外)赋值,例如:int n = m;
2、引用类型赋值,例如:List<String> list = anotherList。
long和double是64位数据,JVM没有明确规定64位赋值操作是不是一个原子操作,不过在x64平台的JVM是把long和double的赋值作为原子操作实现的。

单条原子操作的语句不需要同步。例如:

public void set(String s) {
    this.value = s;
}

但是,如果是多行赋值语句,就必须保证是同步操作,例如:

class Pair {
    int first;
    int last;
    public void set(int first, int last) {
        synchronized(this) {
            this.first = first;
            this.last = last;
        }
    }
}

有些时候,通过一些巧妙的转换,可以把非原子操作变为原子操作。例如,上述代码如果改造成:

class Pair {
    int[] pair;
    public void set(int first, int last) {
        int[] ps = new int[] { first, last };
        this.pair = ps;
    }
}

为什么多行赋值是不安全的?

当多个线程同时运行时,线程的调度由操作系统决定,程序本身无法决定。因此,任何一个线程都有可能在任何指令处被操作系统暂停,然后在某个时间段后继续执行。

当执行完第一个赋值操作后,此时该线程被操作系统暂停。另外一个线程开始执行时,修改了第二个赋值操作的引用,然后第二个线程也被暂停,第一个线程继续执行后继续进行第二个变量的赋值操作。结果就会造成第二个线程中的变量被第一个线程中设置的替换了。

 

参考:https://www.liaoxuefeng.com/wiki/1252599548343744/1306580844806178

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读