简述 Java 中的线程同步机制,synchronized 关键字和 ReentrantLock 的区别是什么?

  1. 语法层面
    synchronized:是 Java 中的关键字,是一种内置的同步机制。它可以修饰方法或者代码块,使用起来比较简洁。例如:
// 同步方法
public synchronized void method() {
    // 同步代码
}

// 同步代码块
public void anotherMethod() {
    synchronized (this) {
        // 同步代码
    }
}

ReentrantLock:是一个类,需要显式地创建锁对象,并调用 lock() 和 unlock() 方法来进行加锁和解锁操作。例如:

import java.util.concurrent.locks.ReentrantLock;

public class LockExample {
    private final ReentrantLock lock = new ReentrantLock();

    public void method() {
        lock.lock();
        try {
            // 同步代码
        } finally {
            lock.unlock();
        }
    }
}
  1. 锁的获取和释放
    synchronized:由 JVM 自动获取和释放锁。当线程进入同步方法或同步代码块时,JVM 会自动获取锁;当线程退出同步方法或同步代码块时,JVM 会自动释放锁。
    ReentrantLock:需要手动获取和释放锁。如果忘记调用 unlock() 方法,会导致锁无法释放,从而产生死锁问题。因此,通常将 unlock() 方法放在 finally 块中,以确保锁一定会被释放。
  2. 锁的特性
    可重入性:两者都具有可重入性,即同一个线程可以多次获取同一把锁而不会发生死锁。
    公平性
    synchronized:是非公平锁,即线程获取锁的顺序是不确定的,可能会导致某些线程长时间得不到锁。
    ReentrantLock:可以通过构造函数指定是公平锁还是非公平锁。公平锁会按照线程请求锁的顺序依次分配锁,保证每个线程都有机会获取锁。例如:
import java.util.concurrent.locks.ReentrantLock;

public class FairLockExample {
    private final ReentrantLock fairLock = new ReentrantLock(true);

    public void method() {
        fairLock.lock();
        try {
            // 同步代码
        } finally {
            fairLock.unlock();
        }
    }
}
  1. 锁的中断
    synchronized:线程在等待获取锁的过程中不能被中断,只能一直等待。
    ReentrantLock:提供了可中断的锁获取方式,即线程在等待获取锁的过程中可以被中断。例如:
import java.util.concurrent.locks.ReentrantLock;

public class InterruptibleLockExample {
    private final ReentrantLock lock = new ReentrantLock();

    public void method() throws InterruptedException {
        lock.lockInterruptibly();
        try {
            // 同步代码
        } finally {
            lock.unlock();
        }
    }
}
  1. 锁的尝试获取
    synchronized:没有提供尝试获取锁的功能,线程只能一直等待锁的释放。
    ReentrantLock:提供了 tryLock() 方法,用于尝试获取锁。如果锁可用,则获取锁并返回 true;如果锁不可用,则立即返回 false,而不会阻塞线程。例如:
import java.util.concurrent.locks.ReentrantLock;

public class TryLockExample {
    private final ReentrantLock lock = new ReentrantLock();

    public void method() {
        if (lock.tryLock()) {
            try {
                // 同步代码
            } finally {
                lock.unlock();
            }
        } else {
            // 锁不可用,执行其他操作
        }
    }
}
posted @ 2025-03-30 21:23  蒟蒻00  阅读(43)  评论(0)    收藏  举报