多线程之volatile

代码一:
如下代码开启2个线程,一个只读,一个只写。
可以看到写线程虽然改变了共享变量,但是只读线程似乎根本不care变化,输出的变量一直是0。

package com.example.multithread.volatiletest;

import java.util.stream.IntStream;

public class VolatileReadOnly {

//    private volatile static int INIT_VALUE=0;
    private static int INIT_VALUE=0;

    private final static int MAX_VALUE=10;

    public static void main(String[] args) {

        //ReadOnly thread cache
        new Thread(()->{
            int currentValue=INIT_VALUE;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            IntStream.rangeClosed(1,5).forEach(i->System.out.println(i+":"+currentValue));
        },"reader only").start();


        //write thread cache
        new Thread(()->{
            while(INIT_VALUE<MAX_VALUE){
                INIT_VALUE++;
                System.out.println(Thread.currentThread().getName()+": "+INIT_VALUE);
            }
        },"writer only").start();
    }
}
执行结果:
writer only: 1
writer only: 2
writer only: 3
writer only: 4
writer only: 5
writer only: 6
writer only: 7
writer only: 8
writer only: 9
writer only: 10
reader only:0
reader only:0
reader only:0
reader only:0
reader only:0

代码二:
如下代码,一个只写线程,一个读写线程。

package com.example.multithread.volatiletest;

public class VolatileReadAndWrite {

//    private volatile static int INIT_VALUE=0;
    private static int INIT_VALUE=0;

    private final static int MAX_VALUE=10;

    public static void main(String[] args) {

        //write thread cache
        new Thread(()->{
            while(INIT_VALUE<MAX_VALUE){
                System.out.println(Thread.currentThread().getName()+": "+INIT_VALUE);
                ++INIT_VALUE;
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"writer only").start();


        //read and write cache
        new Thread(()->{
            int currentValue=INIT_VALUE;
            while(currentValue<MAX_VALUE){
                System.out.println(Thread.currentThread().getName()+": " + INIT_VALUE);
                currentValue=++INIT_VALUE;
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"reader and writer").start();
    }
}

执行结果:
writer only: 0
reader and writer: 1
reader and writer: 2
writer only: 2
reader and writer: 4
writer only: 4
reader and writer: 6
writer only: 6
reader and writer: 8
writer only: 8
reader and writer: 10

在这里插入图片描述
1.如上是JMM简图,cpu执行计算时,会将主内存中的数据复制一份到cpu缓存中,后续操作与缓存交互(cpu与主内存速度差很大,与cpu缓存速度差距不大)。

2.代码一中的读线程由于只有只读动作,cpu后续的计算操作只会与cpu缓存交互,缓存中的数据是程序开始执行时主内存的一个副本,写线程写回主内存的数据并未影响到读线程缓存数据。

3.代码二中的读写线程由于有写的动作,该线程会去主内存中重新加载最新数据到cpu缓存中。输出结果也是不连续的,说明写线程同步回主内存的结果已经被读写线程获取到。

4.为了保证共享变量被一个线程修改后,别的线程可以读取中最新的数据,需要在共享变量前加上volatile关键字。这样共享数据发生改变时,写线程会通过总线通知使用该共享变量的缓存失效,这样cpu在需要使用到共享变量时会去主内存中重新加载并存到cpu缓存中。volatile保证了共享变量在不同线程间的修改可见性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值