作者平台:
| CSDN:https://blog.csdn.net/qq_41153943(ID:江夏、)
| 掘金:https://juejin.cn/user/651387938290686(ID:jiangxia_1024)
| 知乎:https://www.zhihu.com/people/1024-paper-96(ID:江夏)
| GitHub:https://github.com/JiangXia-1024?tab=repositories
| 微信公众号:1024笔记
本文一共1784字,预计阅读11分钟
Synchronized和ReentrantLock都是Java中实现线程同步的机制,它们的目的都是为了保证多个线程访问共享资源时的互斥性和可见性。
Synchronized 的实现原理是基于 Java 中的内置监视器锁(Intrinsic Lock)或称作对象锁(Object Lock),每个 Java 对象都有一个与之关联的锁。
当一个 synchronized 代码块执行时,会首先尝试获得内置监视器锁。如果锁已经被其他线程持有,则当前线程将进入阻塞状态,直到该锁被释放为止;如果锁未被持有,则当前线程获得该锁。在 synchronized 块结束时,会自动释放锁。
ReentrantLock 则是通过 java.util.concurrent.locks.ReentrantLock 类来实现的,它利用了 Java中的AQS(AbstractQueuedSynchronizer) 来实现线程的同步,它允许重入特性,即同一线程可以对已经获取到的锁再次进行请求,如果不支持重入,则会java.lang.IllegalMonitorStateException异常。
2、ReentrantLock 和 synchronized的区别
一般来说ReentrantLock 和 synchronized 相比,具有以下优点:
1. 可以实现公平锁和非公平锁:ReentrantLock 的构造函数中提供了一个布尔类型的参数 fair,可以选择创建公平锁还是非公平锁。而 synchronized 总是非公平锁。
2. 支持多个 Condition 对象:ReentrantLock 中的 Condition 类可以创建多个等待队列,以便更细粒度地控制线程的唤醒。
3. 支持中断等待锁的线程:通过 ReentrantLock 的 lockInterruptibly 方法,可以实现对等待锁的线程进行中断操作。synchronized 则无法中断等待锁的线程。
4. 提供了一些高级功能:如 tryLock() 尝试获得锁但不阻塞;lockInterruptibly() 能够响应线程的中断请求。
在使用 ReentrantLock 时,需要手动释放锁,否则可能会导致死锁等问题。
总结下来,synchronized 和 ReentrantLock 都可以实现线程同步,但在特定的场景下有着各自的优缺点。通常情况下,synchronized 更加简单易用,而 ReentrantLock 在某些复杂场景下能够提供更丰富的功能。
3、代码演示
接下来代码分别演示Synchronized和ReentrantLock的使用:
使用 synchronized 实现线程同步的示例代码:
public class SynchronizedDemo {private int count = 0;public synchronized void increment() {// 对临界区进行加锁保护count++;}public static void main(String[] args) throws Exception {final SynchronizedDemo demo = new SynchronizedDemo();// 创建两个线程并启动Thread t1 = new Thread(new Runnable() {public void run() {for (int i = 0; i < 100000; i++) {demo.increment();}}});t1.start();Thread t2 = new Thread(new Runnable() {public void run() {for (int i = 0; i < 100000; i++) {demo.increment();}}});t2.start();// 等待两个线程执行完毕t1.join();t2.join();// 输出结果System.out.println("count = " + demo.count);}}
在 increment 方法上添加 synchronized 关键字,可以实现对临界区代码块的互斥访问,从而能够确保多个线程在同时对共享变量 count 进行修改时不会发生冲突。
使用 ReentrantLock 实现线程同步的示例代码如下:
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockDemo {private int count = 0;private Lock lock = new ReentrantLock();public void increment() {// 上锁lock.lock();try {count++;} finally {// 释放锁lock.unlock();}}public static void main(String[] args) throws Exception {final ReentrantLockDemo demo = new ReentrantLockDemo();// 创建两个线程并启动Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 100000; i++) {demo.increment();}}});t1.start();Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 100000; i++) {demo.increment();}}});t2.start();// 等待两个线程执行完毕t1.join();t2.join();// 输出结果System.out.println("count = " + demo.count);}}
在使用 ReentrantLock 时,最好在 finally 块中进行解锁操作,确保线程不会因为被锁死而无法释放锁。另外,在声明 ReentrantLock 变量时,尽量将其设置成 private,并给出相应的 getter/setter 方法,这样能够防止直接修改内部状态。
4、总结
Synchronized 和 ReentrantLock 都可以实现线程同步,但在特定的场景下有着各自的优缺点。通常情况下,synchronized 更加简单易用,而 ReentrantLock 在某些复杂场景下能够提供更丰富的功能。
最后感谢大家的关注!
-END-
-
SpringCloud系列:OpenFeign组件
-
SpringCloud系列:如何使用JWT进行身份验证
-
SpringCloud系列:服务雪崩、服务熔断、服务降级
-
SpringCloud系列:Hystrix Dashboard的简单使用
-
SpringCloud系列:服务网关组件Gateway(下)
-
SpringCloud系列:服务网关组件Gateway(上)
本篇文章来源于微信公众号:作者:原创 江夏 1024笔记 1024笔记 微信号 Jang_1024 功能介绍 努力就行了,其他的交给时间! 发表于
转载地址:https://mp.weixin.qq.com/s/AN0eKCARZAw11C1c040-qQ
微信扫描下方的二维码阅读本文

Comments NOTHING