多线程学习笔记2-volatile

volatile关键字
  • 保证线程可见性
public class VolatileDemo {

    /*volatile*/ boolean flag = true;

    public void m() {
        System.out.println("m start...");
        while (flag) {
            //do nothing
        }
        System.out.println("m end...");
    }

    public static void main(String[] args) {
        VolatileDemo volatileDemo = new VolatileDemo();
        new Thread(volatileDemo::m).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        volatileDemo.flag = false;

    }

}

未加volitale:

m start…

加volitale:

m start…

m end…

原因: 如图所示,堆内存中存在flag的值为true,线程1、线程2分别拷贝了堆内存中的flag副本,然而当线程1改变了flag为false的时候,线程2是get不到flag的值为false,除了对变量加了volatile修饰

在这里插入图片描述

  • MESI(缓存一致性协议)
  • 禁止指令重排序

1.double check lock例子,一下是代码

代码

初始化时int类型的a

第一步:初始化为0

第二步:赋值,假设为8

第三步:将赋好的值给变量a
这三条指令,当不加volatile修饰a的时候,指令可能会重排序,导致的情况就是半初始化的时候,a=0,但是我们要的结果是a=8,这就造成意外的结果了

锁粗化 锁细化

锁细化:一般情况下,只对影响的代码做锁细化,例如count++等,其他没有多线程安全问题的可以不用加锁,这个称为锁细化
锁粗化:需要频繁的用到锁,如果锁太细反而影响性能,因此一般可以将锁粗化

CAS(无锁优化 自旋)
  • Compare And Set

cas(V,Expected,NewValue)
if V == E
V = NewValue
otherwise try again or fail
CPU原语支持

  • ABA问题

对引用类型会产生问题,对值类型不影响
1.加version

2.A 1.0

3.B 2.0

4.A 1.0

cas(version)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值