java内存模型的三大特性分别是原子性 ,可见性,有序性(volatile 保证可见性,有序性,但不保证原子性)

三大特性分别是原子性 ,可见性,有序性

原子性:指一个操作是不可中断的,即使是多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰

可见性:指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。显然,对于串行程序来说,可见性问题 是不存在。因为你在任何一个操作步骤中修改某个变量,那么在后续的步骤中,读取这个变量的值,一定是修改后的新值。但是这个问题在并行程序中就不见得了。如果一个线程修改了某一个全局变量,那么其他线程未必可以马上知道这个改动。

有序性:对于一个线程的执行代码而言,我们总是习惯地认为代码的执行时从先往后,依次执行的。这样的理解也不能说完全错误,因为就一个线程而言,确实会这样。但是在并发时,程序的执行可能就会出现乱序。给人直观的感觉就是:写在前面的代码,会在后面执行。有序性问题的原因是因为程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。
分析代码:(这段代码的执行结果总是小于等于10000)

 public static volatile int num = 0;

    public static void main(String[] args) {
        Thread[] thread = new Thread[10];
        for (int i = 0; i < thread.length; i++) {
            thread[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 1000; j++) {
                        add();
                    }

                }
            });
            thread[i].start();
        }
        System.out.println(num);

    }

    public static void add() {
        num++;
    }

解释如图:(解释如上的代码)在这里插入图片描述

public static volatile int x = 0, y = 0;

    public static void main(String[] args) throws InterruptedException {
        x=0;
        y=0;
        Set<String> set = new HashSet<>();
        Map<String, Integer> map = new HashMap<>();
        map.clear();
        for (int i = 0; i < 1000; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int a = y;
                    x = 1;
                    map.put("a", a);
                }
            });
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    int b = x;
                    y = 1;
                    map.put("b", b);
                }
            });
            thread.start();
            thread1.start();
            thread.join();
            thread1.join();
            set.add("a=" + map.get("a") + "," + "b=" + map.get("b"));
            System.out.println(set);
        }
    }


接着分析一下这段代码:居然会出现a=1,b=1的情况
当a=1时,说明y=1
此时说明线程二先执行完了int b=x(此时x应该等于零才对)。
怎么会出现这种情况???????????
有序性问题的原因是因为程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值