• synchronized与ReentrantLock的区别


    在这里插入图片描述
    相同点:
    1.都是可重入锁。
    2.都保证了可见性与互斥性。
    3.都可以用于控制多线程对共享对象的访问。
    不同点:
    1.来源:
    synchronized是java中的关键字,是JVM级别的锁;而ReentrantLock是Lock接口下的一个实现类,是API层面的锁。

    2.异常是否释放锁:
    synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而ReentrantLock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。)
    3.相比synchronized,ReentrantLock增加了一些高级功能:
    3.1等待可中断。
    3.2ReentrantLock可以指定是公平锁还是非公平锁。
    3.3用ReentrantLock类结合Condition实例可以实现“选择性通知”。
    4.是否知道获取锁:
    ReentrantLock可以通过trylock来知道有没有获取锁,而synchronized不能。

    5.ReentrantLock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)

    6.在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,此时优先使用synchronized;而当竞争资源非常激烈时(即有大量线程同时竞争),此时ReentrantLock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
    7.锁机制:
    synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。

    而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。

    现代的CPU提供了指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet() 就用这些代替了锁定。这个算法称作非阻塞算法,意思是一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。

  • 相关阅读:
    MAVEN在IDEA中的使用
    想炒期货是如何开户的?
    Redis持久化RDB,AOF
    如何基于 esp-at 固件测试 TCP (UART 转 WiFi 透传)吞吐?
    Neo4j:一、CQL语句
    原子范数初探:以到达角估计为例
    el-input无法输入
    刷题记录:NC15322强迫症的序列
    什么是数据结构?什么是算法?怎么学习数据结构与算法?
    蓝桥杯(3.6)
  • 原文地址:https://blog.csdn.net/m0_53328194/article/details/125612150