Java 高并发编程详解 4.0 volatile轻量级锁

volatile关键字

作用:轻量级锁,用于多线程的数据共享一致问题,只适用于类变量和成员变量,保证其可见性和有序性。

volatile简单了解


/**
 * volatile 关键字简单了解
 * 1个线程读数据
 * 1个线程改数据
 * 查其执行情况如何
 */
public class VolatileFoo {
    // 最大值
    private final static int MAX = 5;
    // 改变的变量
    private volatile static int value = 0;

    public static void main(String[] args) {
        // 读的线程
        new Thread(() ->{
            //发现本地值和类的变量值不一样时输出信息
            int nowValue = value;
            while (nowValue < MAX){
                if (nowValue != value){
                    System.out.println("值正在从 "+nowValue+" 改变成 "+value);
                    nowValue = value;
                }
            }
        },"reader").start();

        // 改的线程
        new Thread(()->{
            int nowValue = value;
            while (nowValue < MAX){
                System.out.println("value 值自增1 :"+(++nowValue));
                value = nowValue;

                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"update").start();
    }

    // 没有加 volatile 时输出  读的线程没有监听到改值 也不会停止线程
    // value 值自增1 :1
    // 值正在从 0 改变成 1
    // value 值自增1 :2
    // value 值自增1 :3
    // value 值自增1 :4
    // value 值自增1 :5


    // 添加 volatile 时 线程中的值添加可视性和有序性,保证该值在改变时一定会将值刷新到主内存中,并将其他线程的内存缓存失效。 
    // value 值自增1 :1
    //值正在从 0 改变成 1
    //value 值自增1 :2
    //值正在从 1 改变成 2
    //value 值自增1 :3
    //值正在从 2 改变成 3
    //value 值自增1 :4
    //值正在从 3 改变成 4
    //value 值自增1 :5
    //值正在从 4 改变成 5

}

并发编程三个重要特性和JMM(Java内存模型)

  1. 并发编程的三个重要特性:原子性,可见性,有序性
  2. JMM:Java内存模型规定所以的变量存在主内存(RAM)中,而每个线程都有自己的本地内存,线程对变量的所有操作都必须在本地内存进行,而不能直接对主内存进行操作,也访问不到其他线程的本地内存。
  3. 两者之间的关系
    3.1 JMM只保证基础类型读取和赋值的原子性,其他均不保证。要使某些代码片段要有原子性,需要使用synchronized或lock来保证。基础类型要自增也可以使用并发包中的atomic中的类库。
    3.2 可见性的保证。在多线程环境中,每个线程第一次读取共享变量时,都是从主内存中获取,再放入本地内存中,后面读取该变量都是从本地内存中取。如果有线程对变量执行更新操作,也是先执行本地内存,再将更新值刷新到主内存中(但是这个刷新到主内存的动作时间不确认,所以可以用volatile来保证更新变量时一定会刷新到主内存,并让其他线程使用该变量一定会从主线程中获取。也可以使用synchronized和lock来保证变量一定会刷新到主内存中)
    3.3 JMM可以保证单线程代码执行结果的一致性(不管执行多少次相同代码,其结果是一样的),但是里面的执行顺序不能保证执行每次一样。而在多线程的情况下就要使用volatile,synchronized,lock来保证其有序性。

volatile和synchronized的区别

  1. 使用上:volatile使用在变量(成员变量和类变量)上,其他的地方不能使用。synchronized使用在方法(普通方法或静态方法)或语句块上,其他地方不能使用。volatile修饰的变量可以为null,而synchronized的语句块中不能为null。
  2. 对于原子性的保证:volatile不能保证原子性,synchronized是一种排他机制,是不能识别线程的中断标识的所以可以保证原子性。
  3. 对于可见性的保证:都可以保证,但volatile是用机器指令(lock;)来保证,而synchronized是通过排他方式使同步代码串行化。
  4. 对于有序性的保证:都可以保证,volatile是通过禁止JVM编译器和处理器进行重排序。synchrnized是通过保证代码块执行结果一样来保证的(不管代码块中的执行顺序)。
  5. 其他:volatile不会使线程阻塞,synchronized会使线程阻塞。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值