synchronized锁

1、锁的概念

自旋锁:在抢锁的时候,已经被一个线程拿到锁,那么当前线程处于循环获取锁,直到拿到锁为止。

乐观锁:在修改数据时是乐观的,假设是能修改成功。如果不成功则重新获取最新值进行修改。

悲观锁:假设数据修改不成功,则在获取数据时就进行加锁

公平锁:顾名思义就是公平获取,遵循先到先得原则,谁先过来就谁先获取锁

非公平锁:先来的不一定先拿到锁。

2、synchronized的理解

synchronized锁是一个可重入的悲观锁,它的底层是使用的cas实现的。当它使用this锁时,每个对象实例后都是一个新的锁。当使用的是对象锁时,则会挨个执行,栗子如下:

public class SynchronizedTest {

    public static void main(String[] args){
        SynchronizedTest demo = new SynchronizedTest();
        SynchronizedTest demo1 = new SynchronizedTest();

        Thread thread = new Thread(()->{
            demo.log();
        });
        Thread thread1 = new Thread(()->{
            demo1.log();
        });
        thread.start();
        thread1.start();
        try {
            thread.join();
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread thread2 = new Thread(()->{
            demo.log1();
        });
        Thread thread3 = new Thread(()->{
            demo1.log1();
        });

        thread2.start();
        thread3.start();
    }

    public synchronized void log(){
        System.out.println("this锁?执行了?");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static synchronized void log1(){
        System.out.println("对象锁?执行了?");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3、synchronized加锁它加在了哪?

在我们的class文件经过编译成二进制字节码文件后,它存在于我们的堆中,它包含了我们对象的实例化的值以及对象中的引用。那么每个对象都会对应的有个对象头,对象头中包含有mark word, class meta address, array length这三部分。

synchronized锁_第1张图片

而mark word中存储的值有哪些?我们可以根据hotspot提供的文档查阅:

synchronized锁_第2张图片

那么mark word中的的值是如何改变的,我们通过jdk的官方https://wiki.openjdk.java.net/display/HotSpot/Synchronization查看:

synchronized锁_第3张图片

偏量锁:在jdk6之后通过参数-xx:-UseBiasedLocking来禁用它,当然默认是启用的。

当偏量锁启用的时候,对象的初始值为0,如果有线程A且只有一个线程使用时则记录thread ID,偏量锁一般情况下是不会释放锁的。当有线程B来进行抢锁时,如果当前对象进行了降级为0那么就会按照禁用偏量锁方式进行重新执行;如果没有降级,那么它就会升级为轻量锁。

当偏量锁禁用时,对象初始值为未加锁,那么当有线程进行加锁时,那么升级为轻量锁,没抢到进行cas自旋抢锁,如果自旋次数达到一定次数后就会升级为重量级锁。所有没有抢到锁的cas操作放入锁池,直到所有的线程抢锁成功且执行完毕,在 降级为未加锁。所有的降级只会降级到未加锁。不会由重量级降级为轻量级。

你可能感兴趣的:(多线程)