synchronized与Lock的异同


一、synchronized与Lock的异同

synchronized与Lock都能进行加锁,不过不同的是Synchronized 是Java的一个关键字,而Lock是java.util.concurrent.Locks 包下的一个接口,底下有不同的实现方式。另外,synchronized可以用在代码块上、方法上;而Lock只能写在代码里。

synchronized在代码执行完或出现异常时自动释放锁;Lock不会自动释放锁,需要在finally中显
示释放锁。Lock的实现让加锁行为更加灵活,可响应中断、可判断是否已获取到锁, 而synchronized 关键字没有这些行为。

public class Test01 {
    
    
    private static final ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args){
    
    
        try {
    
    
            // 获取锁
            lock.lock();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            // 释放锁
            lock.unlock();
        }
    }
}

二、synchronized的底层实现原理

1、synchronized作用在代码块时,它的底层是通过monitorenter、monitorexit指令来实现的。

  • monitorenter:
    每个对象都是一个监视器锁(monitor),当monitor被占用时就会处于锁定状态,线程执行
    monitorenter指令时尝试获取monitor的所有权,过程如下:
    如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor
    的所有者。如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1。如果其
    他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获
    取monitor的所有权。
  • monitorexit:
    执行monitorexit的线程必须是objectref所对应的monitor持有者。指令执行时,monitor的进入
    数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个
    monitor阻塞的线程可以尝试去获取这个monitor的所有权。

2、方法的同步并没有通过 monitorenter 和 monitorexit 指令来完成,不过相对于普通方法,其常量
池中多了 ACC_SYNCHRONIZED 标示符。JVM就是根据该标示符来实现方法的同步的:

当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。

三、synchronized可以修饰静态方法和静态代码块吗

synchronized可以修饰静态方法,但不能修饰静态代码块。
当修饰静态方法时,监视器锁(monitor)便是对象的Class实例,因为Class数据存在于永久代,因此
静态方法锁相当于该类的一个全局锁。

四、ReentrantLock的实现原理

ReentrantLock 是基于 AQS 实现的, 即 AbstractQueuedSynchronizer 的缩写,具体的看一看这篇Java并发包的灵魂AbstractQueuedSynchronizer

猜你喜欢

转载自blog.csdn.net/weixin_44153131/article/details/129785304
今日推荐