java 之 读写锁 线程间互斥

本文介绍了一个使用读写锁实现线程安全的队列和缓存系统的示例。通过ReentrantReadWriteLock确保多个读操作可以同时进行,而写操作则需要独占锁。这提高了并发性能,尤其是在读操作远多于写操作的场景中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 线程间互斥
 * @author ETHAN
 *
 */
public class ReadWriteLockTest {

	public static void main(String[] args) {
		final Queue3 q3 = new Queue3();
		for(int i=0;i<3;i++) {
			//三个读的线程
			new Thread() {
				public void run() {
					while(true) {
						q3.get();
					}
				}
			}.start();
			
			//三个写的线程
			new Thread() {
				public void run() {
					while(true) {
						q3.put(new Random().nextInt(100000));
					}
				}
			}.start();
		}
	}

}

/**
 * 读和写要互斥,放在一个类里
 * 读锁 不互斥,读和写锁互斥,写写锁互斥
 * @author ETHAN
 *
 */
class Queue3 {
	private Object data = null;//共享数据
	//不能用Lock,得用他的子类
	private ReadWriteLock rwl = new ReentrantReadWriteLock();
	
	public void get() {
		rwl.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName()+ " be ready to read data!");
			Thread.sleep((long)(Math.random()*1000));
			System.out.println(Thread.currentThread().getName()+" have read data: "+data);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			rwl.readLock().unlock();
		}
	}
	
	public void put(Object data) {
		rwl.writeLock().lock();
		
		try {
			System.out.println(Thread.currentThread().getName()+ " be ready to write data!");
			Thread.sleep((long)(Math.random()*1000));
			this.data = data;
			System.out.println(Thread.currentThread().getName()+" have write data: "+data);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			rwl.writeLock().unlock();
		}
	}
}


import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 缓存系统
 * @author ETHAN
 *
 */
public class CacheDemo {

	private Map<String,Object> cache = new HashMap<String, Object>();
	
	public static void main(String[] args) {
		
	}
	
	private ReadWriteLock rwl = new ReentrantReadWriteLock();
	
	public Object getData(String key) {
		rwl.readLock().lock();
		Object value = null;
		try {
			value = cache.get(key);
			if(value==null) {
				rwl.readLock().unlock();
				//挂上写锁,查数据
				rwl.writeLock().lock();
				try {
					//再检查一次,防止其他线程,因为都可读,不互斥
					if(value==null) {
						value = "xxx";//query db
					}
				} finally {
					rwl.readLock().lock();//downgrade by acquiring the readlock
					rwl.writeLock().unlock();//有一种更新锁
				}
				
			} 
		} finally {
			rwl.readLock().unlock();
		}
		
		return value;
	}
}


### Java读写锁互斥的区别及用法 #### 一、概念对比 读写锁(`ReadWriteLock`),也称为『共享-独占』,其核心特性在于实现了 **共享,独占** 的机制[^1]。这意味着多个线程能够并发地进行操作而不会相互干扰;然而,在任何时间点上仅允许一个线程持有权限,并且此时不允许其他任何形式的访问。 相比之下,互斥(Mutex Lock 或 `ReentrantLock` 类型)提供了一种更严格的控制方式——即无论是还是的请求都必须排队等候当前定资源的操作完成之后才能继续执行。换句话说,它并不区分具体的访问模式而是简单粗暴地阻止一切竞争性的尝试直至前序任务结束并释放该对象上的所有权[^4]。 #### 二、适用场景分析 对于那些频繁发生取动作但更新相对较少的数据结构来说,采用读写锁无疑更加高效合理。因为在这种情况下,大部分时间内都可以让尽可能多的工作单元同时获取到所需的信息而不必担心同步问题所带来的额外开销。例如在一个大型网站的应用程序中维护用户配置文件副本时就非常适合运用此类策略来优化性能表现。 另一方面,如果业务逻辑涉及到大量修改或者存在高度不确定性的交互流程,则可能更适合选用传统的互斥方案以确保绝对的安全性一致性。比如银行转账系统中的账户余额调整过程就需要严格遵循串行化原则从而杜绝潜在的风险隐患。 #### 三、具体实现案例展示 下面给出一段基于 `ReentrantReadWriteLock` 实现简易缓存功能的例子: ```java import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class Cache<K, V> { private final ReadWriteLock lock = new ReentrantReadWriteLock(); public void put(K key, V value){ lock.writeLock().lock(); // 获取 try{ System.out.println(Thread.currentThread().getName()+" write 操作执行"); // 执行实际存储操作... }finally{ lock.writeLock().unlock(); // 解除 } } @SuppressWarnings("unchecked") public V get(K key){ lock.readLock().lock(); // 获取 try{ // 返回查询结果... return (V)"模拟返回值"; }finally{ lock.readLock().unlock(); // 解除 } } } ``` 值得注意的是,上述代码片段展示了如何利用读写锁构建一个多线程安全的缓存组件。其中特别强调了无法创建条件变量的事实,这表明在设计阶段应当充分考虑到这一点以免造成不必要的麻烦[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值