ReentrantLock
和 synchronized
都是Java中用于实现线程同步的手段,但它们之间存在一些关键的区别:
-
锁的类型:
synchronized
是一种内置的语言级别的同步机制,它既可以修饰实例方法,也可以修饰静态方法,还可以修饰代码块。ReentrantLock
是一个具体的类,位于java.util.concurrent.locks
包中,是一个显式的锁机制。
-
锁的公平性:
synchronized
无法指定锁的公平性,即锁的获取是不公平的,可能导致线程饥饿。ReentrantLock
允许你指定锁的公平性,即可以按照线程等待锁的顺序来获取锁。
-
锁的尝试机制:
synchronized
无法尝试获取锁,一旦进入同步代码块或方法,其他线程必须等待当前线程释放锁。ReentrantLock
提供了tryLock()
方法,可以试图获取锁而不阻塞,如果锁不可用,可以立即返回或者在指定的等待时间内尝试获取锁。
-
锁的可中断性:
synchronized
不能响应中断,一旦线程进入synchronized
同步代码块,其他线程必须等待其完成。ReentrantLock
可以响应中断,当尝试获取锁的线程在等待时,如果线程被中断,它将立即收到InterruptedException
。
-
条件变量:
synchronized
需要借助Object
的wait()
、notify()
和notifyAll()
方法来实现条件变量的功能。ReentrantLock
提供了与条件变量配套的Condition
接口,通过newCondition()
方法创建,可以更灵活地控制多个条件变量。
-
锁绑定多个条件:
synchronized
只能与一个条件(即对象的监视器)绑定。ReentrantLock
可以绑定多个条件变量。
-
性能:
- 在竞争激烈的环境下,
synchronized
的性能可能不如ReentrantLock
,因为synchronized
的锁获取和释放需要多次上下文切换。 ReentrantLock
在竞争激烈的环境下性能更好,因为它减少了上下文切换的次数。
- 在竞争激烈的环境下,
-
锁的可重入性:
synchronized
和ReentrantLock
都是可重入锁,同一个线程可以多次获得同一把锁。
-
API的丰富性:
synchronized
的API较为简单,功能有限。ReentrantLock
提供了更多的高级功能,如尝试非阻塞获取锁、可中断地获取锁等。
总的来说,ReentrantLock
提供了比synchronized
更多的灵活性和控制能力,适用于需要更复杂同步控制的场景。然而,synchronized
由于其简单性和在轻量级锁定操作中的良好性能,仍然是许多简单同步问题的首选。
下面我将提供一些简单的代码示例来展示ReentrantLock和synchronized的使用
使用synchronized的代码示例
public class SynchronizedExample {public void synchronizedMethod() {synchronized (this) {// 临界区代码System.out.println("Synchronized method accessed by " + Thread.currentThread().getName());}}public static void main(String[] args) {SynchronizedExample example = new SynchronizedExample();// 创建线程并启动Thread thread1 = new Thread(() -> example.synchronizedMethod());Thread thread2 = new Thread(() -> example.synchronizedMethod());thread1.start();thread2.start();}
}
使用ReentrantLock的代码示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {private final Lock lock = new ReentrantLock();public void lockedMethod() {lock.lock(); // 获取锁try {// 临界区代码System.out.println("ReentrantLock method accessed by " + Thread.currentThread().getName());} finally {lock.unlock(); // 释放锁}}public static void main(String[] args) {ReentrantLockExample example = new ReentrantLockExample();// 创建线程并启动Thread thread1 = new Thread(() -> example.lockedMethod());Thread thread2 = new Thread(() -> example.lockedMethod());thread1.start();thread2.start();}
}
使用ReentrantLock的公平锁示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class FairReentrantLockExample {private final Lock lock = new ReentrantLock(true); // 公平锁public void lockedMethod() {lock.lock(); // 获取锁try {// 临界区代码System.out.println("Fair ReentrantLock method accessed by " + Thread.currentThread().getName());} finally {lock.unlock(); // 释放锁}}public static void main(String[] args) {FairReentrantLockExample example = new FairReentrantLockExample();// 创建线程并启动Thread thread1 = new Thread(() -> example.lockedMethod());Thread thread2 = new Thread(() -> example.lockedMethod());thread1.start();thread2.start();}
}
使用ReentrantLock的尝试获取锁示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class TryLockExample {private final Lock lock = new ReentrantLock();public void lockedMethod() {if (lock.tryLock()) { // 尝试获取锁try {// 临界区代码System.out.println("TryLock method accessed by " + Thread.currentThread().getName());} finally {lock.unlock(); // 释放锁}} else {System.out.println("TryLock failed, lock is held by another thread.");}}public static void main(String[] args) {TryLockExample example = new TryLockExample();// 创建线程并启动Thread thread1 = new Thread(() -> example.lockedMethod());Thread thread2 = new Thread(() -> example.lockedMethod());thread1.start();thread2.start();}
}
这些示例展示了synchronized和ReentrantLock的基本用法,以及ReentrantLock的一些高级特性,如公平锁和尝试获取锁。
完结,撒花!求赞求关注! 有问题可威:c_-j_-c