并发编程之同步锁(下)

锁的具体实现

先上图再上代码验证
在这里插入图片描述

偏向锁demo

public class LockDemo {
    Object o=new Object();

    public static void main(String[] args) {
        LockDemo demo=new LockDemo(); //o这个对象,在内存中是如何存储和布局的。
         System.out.println(ClassLayout.parseInstance(demo).toPrintable());
        System.out.println("加锁之后。。。。。。");
         synchronized (demo){
             System.out.println(ClassLayout.parseInstance(demo).toPrintable());
         }
    }
}

未加锁之前的打印
在这里插入图片描述
第一个字节的最后三位就是001,对应上图无锁状态。

加锁后的打印
在这里插入图片描述
第一个字节的最后三位是000对应上图轻量级锁,不应该是偏向锁吗。

奇怪了?怎么会是轻量级锁。因为默认情况下偏向锁是关闭状态。因为main方法启动时,会有很多隐藏的jvm线程在执行,很容易升级为轻量级锁,所以很多时候没必要开启。

开启偏向锁再打印

-XX:BiasedLockingStartupDelay=0

在这里插入图片描述
发现未同步之前就已经获得偏向锁了,原因还是JVM的一些匿名对象在主线程执行之前就已经获得了偏向锁

重量级锁Demo

public class SynchronizedDemo {
    public static void main(String[] args) {
        Demo testDemo = new Demo();
        Thread t1 = new Thread(() -> {
            synchronized (testDemo){
                System.out.println("t1 lock ing");
                System.out.println(ClassLayout.parseInstance(testDemo).toPrintable());
            }
        });
        t1.start();
        synchronized (testDemo){
            System.out.println("main lock ing");
            System.out.println(ClassLayout.parseInstance(testDemo).toPrintable());
        }
    }
}

在这里插入图片描述
第一个字节最后3位010,对应开始的图重量级锁的状态。

CAS(有点类似于数据库通过version来实现乐观锁的感觉)

CAS这个在Synchronized底层用得非常多,它的全称有两种

  • Compare and swap
  • Compare and exchange
    就是比较并交换的意思。它可以保证在多线程环境下对于一个变量修改的原子性

CAS的原理很简单,包含三个值

  • 当前内存值(V)、
  • 预期原来的值(E)
  • 期待更新的值(N)
    如果V==E,那么就修改V为N。

CAS底层实现

不难想到其实还是会用到锁的机制

JVM源码
在这里插入图片描述
可以看到LCOK_IF_MP就是判断是否是多核,多核情况下CAS才可能有问题,如果是的话那么就加锁。

可以理解为这样的代码最后

public synchronized int compareAndSwap(int expectedValue, int newValue) {
        //内存值V
        int oldValue = value;
        //预期值A等于内存值V
        if (oldValue == expectedValue) {
            //将修改值B赋值给内存值V
            value = newValue;
        }
        //返回内存值V
        return oldValue;
    }

ABA问题

内存值V被其他线程多次修改,最终又改回了预期值A,但是这种预期值其实不是预期值了。

  • 例:预期值为5,内存值最初为5,被另一个线程改为7,然后又被改成5,此时预期值与内存值进行值的比较发现没有变化,就认为中途没有其他线程操作
  • 优化方案,对数据加上版本号
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值