synchronized 、volatile 以及 ReentrantLock 的区别

一、synchronized 和 volatile 的区别

synchronized 关键字和 volatile 关键字是两个互补的存在。

  • volatile 关键字是线程同步的轻量实现,所以 volatile 性能比 synchronized 关键字要好。但是 volatile 关键字只能用于修饰变量,而 synchronized 关键字可用于修饰方法以及代码块。
  • volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都可以保证。
  • volatile 关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性。

 

二、synchronized 和 ReentrantLock 的区别

2.1 ReentrantLock 是什么?

ReentrantLock 实现了 Lock 接口,是一个可重入且独占式的锁,和 synchronized 关键字类似。但是 ReentrantLock 更灵活、更强大,增加了轮询、超时、中断、公平锁和非公平锁等高级功能。

2.2 公平锁和非公平锁

  • 公平锁:

        锁被释放之后,先申请的线程先得到锁。性能较差一些,因为公平锁为了保证时间上的绝对顺序,上下文切换更频繁。

  • 非公平锁:

        锁被释放之后,后申请的线程可能会先获获取到锁,是随机或者按照其他优先级排序的。性能更好,但可能会导致某些线程永远无法获取锁。

 

2.3 synchronized 和 ReentrantLock 

  • 两者都是可重入锁

        可重入锁也叫递归锁,指的是线程可以再次获取自己的内部锁。比如一个线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的,如果是不可重入锁,就会造成死锁。JDK 提供的所有 Lock 的实现类,包括 synchronized 关键字锁都是可重入的。

        例如,下面代码中,method1() 和method2() 都被 synchronized 关键字修饰,method1() 调用了 method2()。

public class SynchronizedDemo {
    public synchronized void method1() {
        System.out.println("方法1");
        method2();
    }

    public synchronized void method2() {
        System.out.println("方法2");
    }
}

由于 synchronized 锁是可重入的,同一个线程在调用 method1() 时可以直接获取当前对象的锁,执行 method2() 的时候可以再次获取这个对象的锁,不会产生死锁问题。如果 synchronized 是不可重入锁,由于该对象的锁已被当前线程锁持有且无法释放,这就导致线程在执行 method2() 时获取锁失败,会出现死锁问题。

  • synchronized 依赖于 JVM 而 ReentrantLock 依赖于 API

synchronized 是依赖于 JVM 实现的,ReentrantLock 是 JDK 层面实现的(也就是 API 层面,需要 lock() 和 unlock() 方法配合 try/finally 语句块来完成)。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值