(笔记)java锁策略,synchronized对比,CAS策略

目录

锁策略:

乐观锁和悲观锁:

轻量级锁和重量级锁:

自旋锁和挂起等待锁:

读写锁和普通互斥锁:

公平锁和非公平锁:

可重入锁和不可重入锁:

对比synchronized:

什么是CAS:

CAS图解:​编辑

自旋锁伪代码:

CAS的ABA问题(重点):

ABA问题解决办法:


锁策略:

乐观锁和悲观锁:

侧重于加锁态度

乐观锁:预期锁竞争不激烈,选择不加锁或者少加锁。

悲观锁:在预期锁竞争激烈,加锁。

轻量级锁和重量级锁:

侧重于加锁过程

轻量级锁:过程简单,消耗资源少,用户态加锁操作就可以完成(java层面)。(乐观锁属于轻量级锁的一种)

重量级锁:过程复杂,消耗资源多,内核态加锁(系统内核)。(悲观锁属于重量级锁的一种)

自旋锁和挂起等待锁:

自旋锁:一直在检查锁资源是否释放,一旦锁资源释放马上获取锁资源。(用户态操作,轻量级,能及时获取锁资源,但是一直检查,浪费资源)

挂起等待锁:不主动检查锁资源,由系统调度分配锁资源。(无法第一时间获取锁资源)

读写锁和普通互斥锁:

读写锁:一个线程对于数据的访问, 主要存在两种操作: 读数据 和 写数据.

两个线程都只是读一个数据 , 此时并没有线程安全问题 . 直接并发的读取即可 .
两个线程都要写一个数据 , 有线程安全问题 .
一个线程读另外一个线程写 , 也有线程安全问题 .
所以
读加锁和读加锁之间 , 不互斥 .
写加锁和写加锁之间 , 互斥 .
读加锁和写加锁之间 , 互斥 .
读写锁适合 "频繁读, 不频繁写" 的场景中。

普通互斥锁:竞争关系,只能一个线程获取锁资源,其他线程要等锁资源被释放。

公平锁和非公平锁:

公平锁:先来后到,先排队的先得,后排队的后得锁资源(现实中这只是一种追求无法做到绝对的公平)

非公平锁:谁先抢到做资源,就是谁的。

公平锁需要消耗资源去专门实现,效率也会有折扣,而非公平锁没有那么多的消耗。java中很多地方默认都是使用的非公平锁。

可重入锁和不可重入锁:

可重入锁:可以对同一把锁加锁多次而不造成死锁,同样解锁的时候也要多次解锁。

不可重入锁:对一把锁连续加锁会造成死锁。

对比synchronized:

既是乐观锁又是悲观锁

既是轻量级锁又是重量级锁

既是自旋锁又是挂起等待锁

是普通互斥锁,非公平锁,可重入锁

在锁竞争不激烈的时候synchronized是轻量级锁乐观锁自旋锁,竞争激烈的时候自动升级为重量级锁悲观锁挂起等待锁

什么是CAS:

CAS(Compare and Swap比较并交换)

伪代码:

boolean CAS(address, expectValue, swapValue) {
 if (&address == expectedValue) {
   &address = swapValue;
        return true;
   }
    return false;
}

即:用一个预期值与内存中的值相比较,若相等则交换否则不操作

CAS图解:

 线程一和线程二均先读取了主内存的值,假设线程一要对值进行修改,则先比较主内存的值与自己先前加载的值是否相等,相等则加一操作,再把值写回主内存。

这时候如果线程二要对值进行修改,则先比较主内存和自己先前加载的值,发现不相同,线程二会重新从主内存加载值

 这时候线程二要再修改,就先和主内存的值比较,相等则修改然后把新修改的值写回主内存

CAS以这种每次都比较原值与主内存值的方式保证了原子性 ,自旋则是在CAS外面包了一层循环让CAS在循环中执行。

自旋锁伪代码:

public class SpinLock {
    private Thread owner = null;
    public void lock(){
        // 通过 CAS 看当前锁是否被某个线程持有. 
        // 如果这个锁已经被别的线程持有, 那么就自旋等待. 
        // 如果这个锁没有被别的线程持有, 那么就把 owner 设为当前尝试加锁的线程. 
        while(!CAS(this.owner, null, Thread.currentThread())){
       }
   }
    public void unlock (){
        this.owner = null;
    }
}

CAS的ABA问题(重点):

假设有两个线程t1和t2,初始值为0,后面如果t1想修改0 的值为1,则要先进行比较,发现相等修改为1,但是在t1执行这个问题的时候可能t2已经执行过操作把0改成了2又把2改回了0,也就是说t1在执行操作的时候,无法判断当前值是否是已经被修改多次的值。

ABA问题解决办法:

可以选择加一个标志位,记录值是否被修改。例如软件更新时都会有一个版本号。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值