单例对象中method1与method2的线程并发控制问题求助
用ReentrantReadWriteLock结合Semaphore实现需求
你之前用synchronized修饰方法的问题在于,synchronized是独占锁,不管调用method1还是method2,同一时间只能有一个线程执行,完全限制了method1的并发能力。而ReentrantReadWriteLock正好能解决这个矛盾,它的读锁支持多线程并发持有,写锁独占,且读写锁互斥,再配合Semaphore就能限制method1的并发数为5。
具体实现代码
import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; // 单例类示例 public class Singleton { private static final Singleton INSTANCE = new Singleton(); private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); private final Lock readLock = rwLock.readLock(); private final Lock writeLock = rwLock.writeLock(); private final Semaphore method1Semaphore = new Semaphore(5); // 限制method1最多5个线程并发 private Singleton() {} public static Singleton getInstance() { return INSTANCE; } public void method1() { try { method1Semaphore.acquire(); // 先获取信号量,控制并发数 readLock.lock(); // 获取读锁 // --- 这里写method1的业务逻辑 --- System.out.println(Thread.currentThread().getName() + " 执行method1"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 } finally { readLock.unlock(); // 释放读锁 method1Semaphore.release(); // 释放信号量 } } public void method2() { writeLock.lock(); // 获取写锁 try { // --- 这里写method2的业务逻辑 --- System.out.println(Thread.currentThread().getName() + " 执行method2"); } finally { writeLock.unlock(); // 释放写锁 } } }
逻辑说明
- 读写锁互斥:
- 当
method2持有写锁时,所有调用method1的线程会阻塞在readLock.lock(),直到写锁释放; - 当有线程持有读锁(即
method1在执行)时,method2会阻塞在writeLock.lock(),直到所有读锁都被释放。
- 当
- Semaphore控制并发数:
method1Semaphore的许可数设为5,确保同一时间最多只有5个线程能进入method1的业务逻辑,满足你对method1的并发限制需求。
- 资源释放保障:
- 锁和信号量的释放都放在
finally块中,避免因异常导致锁未释放、信号量泄漏,防止死锁问题。
- 锁和信号量的释放都放在
额外注意
- 如果需要公平锁(让等待时间最长的线程优先获取锁),可以创建
ReentrantReadWriteLock时传入true:new ReentrantReadWriteLock(true); - 单例模式要确保线程安全(示例中用饿汉式,本身是线程安全的),避免多个实例导致锁失效。
内容的提问来源于stack exchange,提问作者user21338878
相关产品推荐
相关产品推荐

