代码改变世界

锁的定义和实现、分类

2022-11-30 09:54  杭伟  阅读(111)  评论(0编辑  收藏  举报

什么是锁?

通过一种抽象的锁来对资源进行锁定。具体来说:操作修改一个数据,在同一时刻只允许一个线程操作,操作完毕才能轮到下一个线程。

在这个过程中,是什么阻止了另一个线程的操作?即是“锁”。

 

Java锁机制:

(主要发生在堆和方法区等线程共享的数据区域)

java中每个对象都有一把锁,锁记录在对象头中。

Object = **对象头 + 实例数据 + 对齐填充字节(Java对象大小必须满足8bit的倍数)

对象头=Mark word+Class pointer

Mark word=锁标志位信息(另有GC+HashCode),如下图:

 

无锁-->偏向锁-->轻量级锁-->重量级锁 四种状态的解释:

代表:synchronized

synchronized底层:monitor,monitor依赖于操作系统:mutex lock

(实际上,synchronized就是monitor管程在java中的实现,有关monitor(管程)的更多信息移步

挂起和唤醒线程需要切换到内核态,Java6开始synchronized开始优化,引入了偏向锁和轻量级锁。

总结锁的四种状态从低到高为:

无锁-->偏向锁-->轻量级锁-->重量级锁 (锁只能升级不能降级)(对应了Mark word中的四种状态):

无锁:CAS,即不通过锁来操作数据

偏向锁:(no mutex lock,no cas),通过线程ID(MarkWord中)直接识别,无竞争状态

轻量锁:自旋(cpu空转)等待数量为1,即有1个竞争者

重量级锁:自旋等待数量超过1,有多个竞争者,即monitor

 

锁的抽象分类:

悲观锁

代表:互斥锁

 

乐观锁(无锁)

代表:CAS(由CPU提供指令级别原子操作)

import java.util.concurrent.atomic.AtomicInteger;

public class Main {
    static AtomicInteger num = new AtomicInteger(0);
    public static void main(String[] args) {
        for(int i=0;i<3;i++){
            Thread t = new Thread(() -> {
                while (num.get() < 1000) {
                    System.out.println("thread name:" + Thread.currentThread().getName() + ":" + num.incrementAndGet());
                }
            });
            t.start();
        }
    }
}
View Code

 

操作系统的锁:synchronized

函数级别的锁:AQS