Java - synchronized

Java synchronized锁

描述

Java语言的关键字,可用来给对象、方法或者代码块修饰加锁,能够保证在同一时刻最多只有一个线程执行该段代码。

表现形式

1、修饰普通同步方法,上锁的的当前实例对象;
2、修饰静态同步方法,上锁的是当前类的class对象;
3、修饰同步方法块,上锁的是synchronized括号中配置的对象;

public class Demo{

    private Integer sum;

    //修饰普通同步方法
    public synchronized void test() {}
    
    //修饰静态同步方法
    public static synchronized void testOne() {}
    
    public void testTwo() {
        //修饰方法块
        synchronized(sum){}
    }
}

锁的优化

在JDK1.6版本之前,synchronized属于重量级锁,效率低下;在JDK1.6版本之后,JVM底层对synchronized做了大量的优化,引入了偏向锁、轻量级锁、自旋锁、适用性自旋锁、锁消除、锁粗化等技术来减少锁操作的开销。
锁主要存在四种状态,依次是:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,他们会随着竞争的激烈而逐渐升级(锁升级后是不能降级的,但是偏向锁可以重置为无锁状态),这种策略是为了提高获得锁和释放锁的效率。

无锁

无锁是指没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时有且只有一个线程能修改成功。
无锁的特点是修改操作会循环内进行,线程会不断的尝试修改共享资源,如果没有冲突就修改成功并退出,否则就会继续循环尝试,如果有多个线程同时修改同一个值,必定会有一个线程能修改成功,而其他修改失败的线程会不断重试直到修改成功。

偏向锁

偏向锁是指当一段同步代码一直被同一个线程所访问时,即不存在多个线程的竞争时,那么该线程在后续访问时便会自动获得锁,从而降低获取锁带来的消耗,即提高性能。

轻量级锁

轻量级锁是指当锁是偏向锁的时候,却被另外的线程所访问,此时,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,线程不会block,从而提供性能。
轻量级锁的获取主要有两种情况:
1、当关闭偏向锁功能时
2、由于多个线程竞争偏向锁导致偏向锁升级为轻量级锁

若当前只有一个等待线程,则该线程将通过自旋进行等待,但是当自旋超过一定次数,轻量级锁会升级为重量级锁。
另外,当一个线程已持有锁,另一个线程在自旋,而此时又有第三个线程来访时,轻量级锁也会升级为重量级锁

重量级锁

重量级锁是指当有一个线程获取锁之后,其余所有等待获取的锁都会处于阻塞状态。

锁升级执行过程

1、检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁
2、如果不是,则使用CAS将当前线程的ID替换Mark Word,如果成功则表示当前线程获得偏向锁,置偏向标志位1
3、如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁
4、当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁
5、如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁;
6、自旋成功,则依然处于轻量级状态
7、自旋失败,则升级为重量级锁

猜你喜欢

转载自blog.csdn.net/jianghuafeng0/article/details/107025012