本文共 4084 字,大约阅读时间需要 13 分钟。
重入锁(Reentrant Lock)是Java并发编程中一种高级的同步机制,主要用于解决多线程程序中共享资源的竞态问题。相比于传统的synchronized关键字,重入锁在性能上有显著提升,尤其是在处理中断和限时等待需求时更加灵活。重入锁通过其内部基于队列的机制,能够更好地管理线程的等待和中断流程。
重入锁主要通过几个关键方法实现其功能:
lock():尝试获取锁,如果锁已被占用,则进入等待状态,直到锁被释放或中断。lockInterruptibly():获取锁,并优先处理中断信号。如果当前线程正在等待锁,中断信号会立即被处理,锁的获取流程会停止。tryLock():尝试获取锁,不进入等待状态。如果锁已被占用,立即返回false,否则返回true,并立即释放锁。unlock():释放锁,允许其他线程获取锁。重入锁的默认实现类ReentrantLock,以及其扩展类ReentrantLock(boolean fair),能够支持公平锁和非公平锁的模式,后者是默认设置。
以下是一个使用重入锁保护临界区资源的典型示例:
public class ReenterLock implements Runnable { private static final ReentrantLock lock = new ReentrantLock(); private static int count = 0; @Override public void run() { for (int i = 0; i < 10000000; i++) { lock.lock(); try { count++; } finally { lock.unlock(); } } } public static void main(String[] args) throws InterruptedException { ReenterLock task = new ReenterLock(); Thread t1 = new Thread(task); Thread t2 = new Thread(task); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("总次数 = " + count); }} 重入锁支持中断机制,可以在等待锁的过程中被中断,这对于解决死锁问题或优化资源利用非常有用。以下是一个典型的死锁案例及其解决方案:
public class IntLock implements Runnable { private static final ReentrantLock lock1 = new ReentrantLock(); private static final ReentrantLock lock2 = new ReentrantLock(); private int currentLock; public IntLock(int lock) { this.currentLock = lock; } @Override public void run() { try { if (currentLock == 1) { lock1.lockInterruptibly(); Thread.sleep(500); lock2.lockInterruptibly(); } else { lock2.lockInterruptibly(); Thread.sleep(500); lock1.lockInterruptibly(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { if (lock1.isHeldByCurrentThread()) { lock1.unlock(); } if (lock2.isHeldByCurrentThread()) { lock2.unlock(); } System.out.println(Thread.currentThread().getId() + ":线程退出"); } } public static void main(String[] args) throws InterruptedException { IntLock task = new IntLock(1); Thread t1 = new Thread(task); Thread t2 = new Thread(task); t1.start(); t2.start(); Thread.sleep(1000); t2.interrupt(); }} 重入锁支持tryLock(long timeout, TimeUnit unit)方法,允许线程在指定的时间内尝试获取锁,避免长时间等待。以下是一个使用限时锁的示例:
public class TimeLock implements Runnable { private static final ReentrantLock lock = new ReentrantLock(); @Override public void run() { boolean locked = lock.tryLock(5, TimeUnit.SECONDS); if (locked) { Thread.sleep(6000); } else { System.out.println("无法获取锁"); } } public static void main(String[] args) { TimeLock task = new TimeLock(); Thread t1 = new Thread(task); Thread t2 = new Thread(task); t1.start(); t2.start(); }} 重入锁支持公平锁模式,通过构造函数ReentrantLock(boolean fair)可以指定锁的公平性。公平锁确保同一资源的竞争按照线程启动的先后顺序进行,避免了饥饿现象。以下是一个公平锁的使用示例:
public class FairLock implements Runnable { private static final ReentrantLock lock = new ReentrantLock(true); @Override public void run() { while (true) { lock.lock(); System.out.println(Thread.currentThread().getName() + "获得锁"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } public static void main(String[] args) { FairLock task = new FairLock(); Thread t1 = new Thread(task, "Thread_t1"); Thread t2 = new Thread(task, "Thread_t2"); t1.start(); t2.start(); }} 重入锁通过其灵活的锁定机制、强大的中断能力以及支持公平锁和限时等待功能,为现代Java程序的多线程编程提供了强大的工具。在实际应用中,重入锁可以有效避免死锁、减少等待时间,并优化资源利用效率。
转载地址:http://hqjo.baihongyu.com/