- 浏览: 7340096 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1546)
- 企业中间件 (236)
- 企业应用面临的问题 (236)
- 小布Oracle学习笔记汇总 (36)
- Spring 开发应用 (54)
- IBatis开发应用 (16)
- Oracle基础学习 (23)
- struts2.0 (41)
- JVM&ClassLoader&GC (16)
- JQuery的开发应用 (17)
- WebService的开发应用 (21)
- Java&Socket (44)
- 开源组件的应用 (254)
- 常用Javascript的开发应用 (28)
- J2EE开发技术指南 (163)
- EJB3开发应用 (11)
- GIS&Mobile&MAP (36)
- SWT-GEF-RCP (52)
- 算法&数据结构 (6)
- Apache开源组件研究 (62)
- Hibernate 学习应用 (57)
- java并发编程 (59)
- MySQL&Mongodb&MS/SQL (15)
- Oracle数据库实验室 (55)
- 搜索引擎的开发应用 (34)
- 软件工程师笔试经典 (14)
- 其他杂项 (10)
- AndroidPn& MQTT&C2DM&推技术 (29)
- ActiveMQ学习和研究 (38)
- Google技术应用开发和API分析 (11)
- flex的学习总结 (59)
- 项目中一点总结 (20)
- java疑惑 java面向对象编程 (28)
- Android 开发学习 (133)
- linux和UNIX的总结 (37)
- Titanium学习总结 (20)
- JQueryMobile学习总结 (34)
- Phonegap学习总结 (32)
- HTML5学习总结 (41)
- JeeCMS研究和理解分析 (9)
最新评论
-
lgh1992314:
[u][i][b][flash=200,200][url][i ...
看看mybatis 源代码 -
尼古拉斯.fwp:
图片根本就不出来好吧。。。。。。
Android文件图片上传的详细讲解(一)HTTP multipart/form-data 上传报文格式实现手机端上传 -
ln94223:
第一个应该用排它网关吧 怎么是并行网关, 并行网关是所有exe ...
工作流Activiti的学习总结(八)Activiti自动执行的应用 -
ZY199266:
获取不到任何消息信息,请问这是什么原因呢?
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息 -
xiaoyao霄:
DestinationSourceMonitor 报错 应该导 ...
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息
java 中 ReentrantReadWriteLock的读锁和写锁的使用
jdk文档中关于ReentrantReadWriteLock类使用的一个很好的例子,以下是具体的介绍:
在使用某些种类的 Collection 时,可以使用 ReentrantReadWriteLock 来提高并发性。通常,在预期 collection很大,读取者线程访问它的次数多于写入者线程,并且 entail 操作的开销高于同步开销时,这很值得一试。例如,以下
是一个使用 TreeMap 的类,预期它很大,并且能被同时访问。
两种锁机制:
1、synchronized
2、ReentrantLock
ReentrantLock是jdk5的新特性,采用ReentrantLock可以完全替代替换synchronized传统的锁机制,而且采用ReentrantLock的方式更加面向对象,也更加灵活,网上有很多关于对比两者锁方式的文章。
读写锁:ReadWriteLock
在多线程的环境下,对同一份数据进行读写,会涉及到线程安全的问题。比如在一个线程读取数据的时候,另外一个线程在写数据,而导致前后数据的不一致性;一个线程在写数据的时候,另一个线程也在写,同样也会导致线程前后看到的数据的不一致性。
这时候可以在读写方法中加入互斥锁,任何时候只能允许一个线程的一个读或写操作,而不允许其他线程的读或写操作,这样是可以解决这样以上的问题,但是效率却大打折扣了。因为在真实的业务场景中,一份数据,读取数据的操作次数通常高于写入数据的操作,而线程与线程间的读读操作是不涉及到线程安全的问题,没有必要加入互斥锁,只要在读-写,写-写期 间上锁就行了。
对于这种情况,读写锁则最好的解决方案!
读写锁的机制:
"读-读"不互斥
"读-写"互斥
"写-写"互斥
即在任何时候必须保证:
只有一个线程在写入;
线程正在读取的时候,写入操作等待;
线程正在写入的时候,其他线程的写入操作和读取操作都要等待;
以下是一个缓存类:用于演示读写锁的操作:重入、降级。
package com.etrip.concurrent.locks; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * * * 两种互斥锁机制: 1、synchronized 2、ReentrantLock ReentrantLock是jdk5的新特性,采用ReentrantLock可以完全替代替换synchronized传统的锁机制,而且采用ReentrantLock的方式更加面向对象,也更加灵活,网上有很多关于对比两者锁方式的文章,这里就不多口舌了,大家baidu、google一下就水落石出了。在本博客中也写关于这两种锁方式实现的经典例子《生产者消费者》。 *@author longgangbai */ public class CachedData { // 缓存都应该是单例的,在这里用单例模式设计: private static CachedData cachedData = new CachedData(); private final ReadWriteLock lock = new ReentrantReadWriteLock();//读写锁 private Map<String, Object> cache = new HashMap<String, Object>();//缓存 private CachedData(){ } public static CachedData getInstance(){ return cachedData; } // 读取缓存: public Object read(String key) { lock.readLock().lock(); Object obj = null; try { obj = cache.get(key); if (obj == null) { lock.readLock().unlock(); // 在这里的时候,其他的线程有可能获取到锁 lock.writeLock().lock(); try { if (obj == null) { obj = "查找数据库"; // 实际动作是查找数据库 // 把数据更新到缓存中: cache.put(key, obj); } } finally { // 当前线程在获取到写锁的过程中,可以获取到读锁,这叫锁的重入,然后导致了写锁的降级,称为降级锁。 // 利用重入可以将写锁降级,但只能在当前线程保持的所有写入锁都已经释放后,才允许重入 reader使用 // 它们。所以在重入的过程中,其他的线程不会有获取到锁的机会(这样做的好处)。试想,先释放写锁,在 // 上读锁,这样做有什么弊端?--如果这样做,那么在释放写锁后,在得到读锁前,有可能被其他线程打断。 // 重入————>降级锁的步骤:先获取写入锁,然后获取读取锁,最后释放写入锁(重点) lock.readLock().lock(); lock.writeLock().unlock(); } } } finally { lock.readLock().unlock(); } return obj; } }
class RWDictionary {
private final Map<String, String> map = new TreeMap<String, String>();
private final ReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock readLock = rwl.readLock();
private final Lock writeLock = rwl.writeLock();
{
map.put("EN", "英国");
map.put("CA", "加拿大");
map.put("FR", "法国");
map.put("CN", "中国");
}
public String get(String key) {
readLock.lock();
try {
return map.get(key);
} finally {
readLock.unlock();
}
}
public String[] allKeys() {
readLock.lock();
try {
return (String[]) map.keySet().toArray();
} finally {
readLock.unlock();
}
}
public String put(String key, String value) {
writeLock.lock();
try {
return map.put(key, value);
} finally {
writeLock.unlock();
}
}
public void clear() {
writeLock.lock();
try {
map.clear();
} finally {
writeLock.unlock();
}
}
}
public class RWDictionaryTest {
public static void main(String[] args) {
RWDictionary rw=new RWDictionary();
String value =rw.get("CN");
System.out.println("value ="+value );
Map<String, String> map = new TreeMap<String, String>();
map.put("EN", "英国");
map.put("CA", "加拿大");
map.put("FR", "法国");
map.put("CN", "中国");
//Collections.synchronizedMap用法如下
Map<String, String> m = Collections.synchronizedMap(map);
Set<String> s = m.keySet(); // Needn't be in synchronized block
synchronized(m) { // Synchronizing on m, not s!
Iterator<String> i = s.iterator(); // Must be in synchronized block
while (i.hasNext()){
RWDictionaryTest.foo(i.next());
}
}
}
public static void foo(String str){
System.out.println(" "+ str+" ");
}
}
评论
try {
use(data);
} finally {
rwl.readLock().unlock();
}
// 读取缓存: public Object read(String key) { lock.readLock().lock(); Object obj = null; try { obj = cache.get(key); if (obj == null) { lock.readLock().unlock(); // 在这里的时候,其他的线程有可能获取到锁 lock.writeLock().lock(); try { if (obj == null) { obj = "查找数据库"; // 实际动作是查找数据库 // 把数据更新到缓存中: cache.put(key, obj); } } finally { // 当前线程在获取到写锁的过程中,可以获取到读锁,这叫锁的重入,然后导致了写锁的降级,称为降级锁。 // 利用重入可以将写锁降级,但只能在当前线程保持的所有写入锁都已经释放后,才允许重入 reader使用 // 它们。所以在重入的过程中,其他的线程不会有获取到锁的机会(这样做的好处)。试想,先释放写锁,在 // 上读锁,这样做有什么弊端?--如果这样做,那么在释放写锁后,在得到读锁前,有可能被其他线程打断。 // 重入————>降级锁的步骤:先获取写入锁,然后获取读取锁,最后释放写入锁(重点) lock.readLock().lock(); lock.writeLock().unlock(); } } } finally { lock.readLock().unlock(); } return obj; }
这段代码为何要降级锁?直接writeLock.unlock()不就好了?
// 读取缓存: public Object read(String key) { lock.readLock().lock(); Object obj = null; try { obj = cache.get(key); } finally{ lock.readLock().unlock(); } if (obj == null) { lock.writeLock().lock(); try { if (obj == null) { obj = "查找数据库"; cache.put(key, obj); } } finally { lock.writeLock().unlock(); } } return obj; }
发表评论
-
Mule ESB 学习笔记(20)Mule和Spring httpinvoker的整合
2013-08-28 13:59 3766mule的配置文件: <?xml version=& ... -
Mule ESB 学习笔记(19)Mule和RSS的整合
2013-08-28 10:08 2601定时扫描特定目录的rss文件: <?xml vers ... -
Mule ESB 学习笔记(18)Mule和ATOM的整合
2013-08-27 20:00 2621定时读取特定文件的rss文件: <?xml ... -
Mule ESB 学习笔记(17)Mule和JMX的整合
2013-08-27 16:48 4065Agent的实现: package com.easyway ... -
Mule ESB 学习笔记(16)CXF SOAP基于SAML的验证的配置
2013-08-27 15:19 3805mule的配置 <mule xmlns:core=& ... -
Mule ESB 学习笔记(15)CXF SOAP基于JKS的验证的配置
2013-08-27 14:57 3876mule的配置如下: <mule xmlns:cor ... -
Mule ESB 学习笔记(14)CXF SOAP基于UsernameToken的验证
2013-08-27 14:16 7955简单需求: 针对在webservice ... -
Mule ESB 学习笔记(13)CSV数据文件到数据库
2013-08-26 17:54 7047简单需求: ... -
Mule ESB 学习笔记(12)JSON转换器的使用
2013-08-26 13:54 9098在许多情况下,可能需要把类转换为js ... -
Mule ESB 学习笔记(11)Web Service Proxy
2013-08-24 19:32 6630一、WebSevice Proxy 简介 ... -
Mule ESB 学习笔记(10)mule事务配置
2013-08-23 16:36 6240在mule的事务可能为jdbc事务,jms事务 ... -
Mule ESB 学习笔记(9)mule配置常用节点解释
2013-08-23 13:27 34461 Mule-config.x ... -
Mule ESB 学习笔记(8)mule和jersey的整合使用
2013-08-23 11:20 3947在项目常用jesery作为rest ... -
Mule ESB 学习笔记(7)服务调用
2013-08-23 10:44 18915一. 服务调用 1. Mule实现并提供Web Servi ... -
Mule ESB 学习笔记(6)配置模式
2013-08-23 10:42 4778为了节省时间,就不翻译了,摘抄重点总结 ... -
Mule ESB 学习笔记(5)异步请求-响应方式
2013-08-22 15:32 35915.4 异步请求-响应方式 异步请求-响应方式即请求方调用 ... -
Mule ESB 学习笔记(4)同步方式
2013-08-22 15:19 42555.3 同步方式 同步方式即请求方调用 ... -
JBOSS EJB3项目启动执行一个任务
2013-08-06 22:26 3845在jboss的项目中,jboss启动 ... -
Jboss @Service的使用
2013-08-06 21:59 1995Jboss有一个扩展的annotation——@Servic ... -
julian Date 计算 和实现
2013-08-01 09:32 4451Qt库里CBSDate类的内部实现用_jd成员进行计算、比较 ...
相关推荐
Java 读写锁是Java并发编程中的一种重要机制,它为多线程环境下的数据访问提供了更为精细的控制。在Java的`java.util....通过阅读和分析`readwritelock`这个示例,开发者可以更好地掌握如何在Java中使用读写锁。
在Java中,ReentrantReadWriteLock类是读写锁的实现,它包含两个锁:读锁(共享锁)和写锁(独占锁)。读锁可以被多个线程同时持有,而写锁是独占的,当写锁被占用时,其他线程既不能获取读锁也不能获取写锁。 5. ...
ReentrantReadWriteLock包含两种类型的锁:读锁(ReadLock)和写锁(WriteLock),它们可以独立地被获取和释放,从而提高了多线程环境下的并发性能。 1. **为什么需要ReentrantReadWriteLock?** - ...
其中`ReentrantReadWriteLock`通过明确区分读锁和写锁来支持并发读操作,而`StampLock`则提供了更灵活的并发控制机制,支持乐观读和悲观读。开发者可以根据具体的应用场景和需求选择合适的锁机制,以达到最佳的并发...
`ReentrantReadWriteLock`实现了`ReadWriteLock`接口,提供了`readLock()`和`writeLock()`方法,分别用来获取读锁和写锁。 #### 3. 读写锁的自定义实现 在没有`ReadWriteLock`的情况下,可以通过`synchronized`...
- **分离性**:读锁和写锁是分离的,读锁之间不互斥,但读写、写读、写写都是互斥的。 - **公平性**:ReentrantReadWriteLock提供公平和非公平两种模式。公平模式下,线程按照等待时间顺序获取锁;非公平模式下,...
6. **读写锁**:读写锁允许多个读线程同时访问资源,但写线程独占资源。Java的`ReentrantReadWriteLock`提供这种功能,提高并发性能。 7. **分段锁**:当数据结构很大时,如ConcurrentHashMap,采用分段锁策略,将...
在读锁的实现中,ReentrantReadWriteLock支持读锁的重入,而写锁同样支持重入,但写锁具有更高的优先级,即使有多个线程在等待读锁,只要写锁被持有,这些线程都将被阻塞。 此外,ReentrantReadWriteLock还提供了...
5. **读写锁** 包括读锁(共享)和写锁(独占),如`java.util.concurrent.locks.ReentrantReadWriteLock`,提高多线程读操作的并发性能。 6. **乐观锁 / 悲观锁** - **乐观锁** 在读取数据时假定不会有其他线程...
读写锁通过`ReentrantReadWriteLock`类的实例来创建,该类提供了`readLock()`和`writeLock()`方法,分别用于获取读锁和写锁。 ```java ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); Lock readLock...
- ReadWriteLock(读写锁):ReentrantReadWriteLock提供了读写分离的锁,允许多个读线程同时访问,但写线程独占资源。 2. **乐观锁** - CAS(Compare and Swap):无锁算法,基于硬件原子操作,检查并更新值,...
读写锁通常包括两个锁:读锁(`ReadLock`)和写锁(`WriteLock`)。当多个线程进行读操作时,它们可以同时获得读锁;当有一个线程进行写操作时,其他所有线程(无论是读还是写)都必须等待。 **示例:** - `...
在Java中,锁主要分为两类:乐观锁和悲观锁。 **乐观锁**是一种非阻塞的锁策略,它假设在读取数据时不会有其他线程修改数据,所以在读取时不加锁。当尝试更新数据时,乐观锁会检查在此期间是否有其他线程修改过数据...
读写锁分为读锁和写锁,读锁允许多个线程同时读取共享资源,而写锁则独占共享资源以进行写操作。读写锁的规则是:读读不互斥,读写互斥,写写互斥。 读写锁的实现原理 读写锁的实现原理可以通过两个 int 变量来...
`ReentrantReadWriteLock`是一种特殊的锁机制,它支持读锁和写锁两种类型,主要用于解决读多写少的场景下的性能问题。当多个线程同时进行读操作时,不会相互阻塞,可以并行执行。但是当一个线程正在执行写操作时,...
读写锁维护一对读锁和写锁,通过读和写锁的分离,提升并发性能。Java 中的 ReentrantReadWriteLock 类是 ReadWriteLock 接口的实现类。 CAS CAS 是 Compare And Swap,即比较和交换。CAS 使用一个期望值与一个变量...
- 在写锁保护下,检查`cacheValid`状态(`@3`行)是为了防止在释放读锁和获取写锁之间的短暂时间窗口内,另一个线程已经完成了写操作。 - 如果数据确实需要更新,执行更新操作,并将`cacheValid`设置为`true`。...
添加和删除元素(写操作)都使用写锁,而读取元素(读操作)则使用读锁。这样,多个线程可以同时读取列表,但只有单个线程能进行修改操作。 读写锁的设计使得在高并发环境下,系统可以更有效地利用资源。然而,也...
- **读写锁(ReadWriteLock)**:ReentrantReadWriteLock是Lock的一个实现,分为读锁(ReadLock)和写锁(WriteLock),允许多个读线程同时访问,但写锁是独占的。 - **条件变量(Condition)**:Lock接口提供了一...