synchronized 和 ReentrantLock 都是 Java 中的同步机制,用于确保在多线程环境下,同一时刻只有一个线程能够访问特定的代码块、方法或对象。它们的区别在于实现方式和性能上。
synchronized、ReentrantLock
- synchronized
- 示例
- ReentrantLock
- 可重入
- 公平性
- 示例
synchronized
synchronized 是关键字,可以用于修饰方法或代码块。当使用 synchronized 修饰方法或代码块时,整个修饰的代码块或方法被锁住,只有当锁被释放时,才能继续执行。(加锁解锁以及锁升级过程由JVM自动控制)
示例
public class BiasLockExample {private static final Object LOCK = new Object();private static int count = 0;public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {synchronized (LOCK) {count++;}}});Thread t2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {synchronized (LOCK) {count++;}}});t1.start();t2.start();try {t1.join();t2.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Count: " + count);}
}
ReentrantLock
ReentrantLock 是 API,通过实现 java.util.concurrent.locks.Lock 接口来提供锁功能。所以就需要手动进行加锁解锁处理,ReentrantLock 提供了更多的高级功能,如可重入、公平性、可设置超时等。
可重入
意味着同一个线程可以多次获得同一个锁。synchronized也有这个特点。
公平性
ReentrantLock分为公平锁和非公平锁(默认非公平锁),具体用法是new ReentrantLock(true/false),当false的时候是非公平锁,true的时候是公平锁,非公平锁和公平锁的区别可以简单理解为:
在公平锁中,先申请锁的线程一定会先获得锁,而不会被后申请锁的线程抢到。而在非公平锁中就不一定了,谁抢到算谁的,不管申请锁的顺序。
示例
import java.util.concurrent.locks.ReentrantLock;/*** ReentrantLock(可重入锁)*/
public class ReentrantLockTest {//创建锁对象(入参为是否开启公平锁)ReentrantLock lock = new ReentrantLock(false);public void method(){String thread_name = Thread.currentThread().getName();System.out.println(thread_name +"当前是否上锁:"+lock.isLocked());//加锁lock.lock();try {Thread.sleep(500);System.out.println(thread_name+"锁用完啦");}catch (Exception e){e.printStackTrace();}finally {//释放锁lock.unlock();}}public static void main(String[] args) {ReentrantLockTest t = new ReentrantLockTest();for (int i = 0; i < 5; i++) {new Thread(() -> {t.method();},"ReentrantLockTest-"+i).start();}for (int i = 5; i < 10; i++) {new Thread(() -> {t.method();},"ReentrantLockTest-"+i).start();}}
}