- 浏览: 980897 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
ReentrantLock 实现了标准的互斥操作,也就是一次只能有一个线程持有锁,也即所谓独占锁的概念。前面的章节中一直在强调这个特点。显然这个特点在一定程度上面减低了吞吐量,实际上独占锁是一种保守的锁策略,在这种情况下任何“读/读”,“写/读”,“写/写”操作都不能同时发生。但是同样需要强调的一个概念是,锁是有一定的开销的,当并发比较大的时候,锁的开销就比较客观了。所以如果可能的话就尽量少用锁,非要用锁的话就尝试看能否改造为读写锁。ReadWriteLock描述的是:一个资源能够被多个读线程访问,或者被一个写线程访问,但是不能同时存在读写线程。也就是说读写锁使用的场合是一个共享资源被大量读取操作,而只有少量的写操作(修改数据)
下面我们用一个ReadWriteLock来实现简单的ConcurrentMap
上面的并发Map我们主要用的读写锁,的读锁和写锁分别控制并发Map的存和取。
ReadWriteLock需要严格区分读写操作,如果读操作使用了写入锁,那么降低读操作的吞吐量,如果写操作使用了读取锁,那么就可能发生数据错误。另外ReentrantReadWriteLock还有以下几个特性:
• 公平性
非公平锁(默认) 这个和独占锁的非公平性一样,由于读线程之间没有锁竞争,所以读操作没有公平性和非公平性,写操作时,由于写操作可能立即获取到锁,所以会推迟一个或多个读操作或者写操作。因此非公平锁的吞吐量要高于公平锁。公平锁 利用AQS的CLH队列,释放当前保持的锁(读锁或者写锁)时,优先为等待时间最长的那个写线程分配写入锁,当前前提是写线程的等待时间要比所有读线程的等待时间要长。同样一个线程持有写入锁或者有一个写线程已经在等待了,那么试图获取公平锁的(非重入)所有线程(包括读写线程)都将被阻塞,
直到最先的写线程释放锁。如果读线程的等待时间比写线程的等待时间还有长,那么一旦上一个写线程释放锁,这一组读线程将获取锁。
• 重入性
读写锁允许读线程和写线程按照请求锁的顺序重新获取读取锁或者写入锁。当然了只有写线程释放了锁,读线程才能获取重入锁。写线程获取写入锁后可以再次获取读取锁,但是读线程获取读取锁后却不能获取写入锁。另外读写锁最多支持65535个递归写入锁和65535个递归读取锁。
• 锁降级
写线程获取写入锁后可以获取读取锁,然后释放写入锁,这样就从写入锁变成了读取锁,从而实现锁降级的特性。
• 锁升级
读取锁是不能直接升级为写入锁的。因为获取一个写入锁需要释放所有读取锁,所以如果有两个读取锁尝试获取写入锁而都不释放读取锁时就会发生死锁。
• 锁获取中断
读取锁和写入锁都支持获取锁期间被中断。这个和独占锁一致。
• 条件变量
写入锁提供了条件变量(Condition)的支持,这个和独占锁一致,但是读取锁却不允许获取条件变量,将得到一个UnsupportedOperationException异常。
• 重入数
读取锁和写入锁的数量最大分别只能是65535(包括重入数)。
下面我们用一个ReadWriteLock来实现简单的ConcurrentMap
package juc.latch; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * ReentrantReadWriteLock实现的简单ConcurrentMap * @author donald * 2017年3月6日 * 下午9:43:24 * @param <K> * @param <V> */ public class SimpleConcurrentMap<K, V> implements Map<K, V> { final ReadWriteLock lock = new ReentrantReadWriteLock(); //读写锁 final Lock r = lock.readLock(); final Lock w = lock.writeLock(); final Map<K, V> map; public SimpleConcurrentMap(Map<K, V> map) { this.map = map; if (map == null) throw new NullPointerException(); } /** * */ public void clear() { w.lock(); try { map.clear(); } finally { w.unlock(); } } /** * */ public boolean containsKey(Object key) { r.lock(); try { return map.containsKey(key); } finally { r.unlock(); } } /** * */ public boolean containsValue(Object value) { r.lock(); try { return map.containsValue(value); } finally { r.unlock(); } } public Set<java.util.Map.Entry<K, V>> entrySet() { throw new UnsupportedOperationException(); } /** * */ public V get(Object key) { r.lock(); try { return map.get(key); } finally { r.unlock(); } } /** * */ public boolean isEmpty() { r.lock(); try { return map.isEmpty(); } finally { r.unlock(); } } /** * */ public Set<K> keySet() { r.lock(); try { return new HashSet<K>(map.keySet()); } finally { r.unlock(); } } /** * */ public V put(K key, V value) { w.lock(); try { return map.put(key, value); } finally { w.unlock(); } } /** * */ public void putAll(Map<? extends K, ? extends V> m) { w.lock(); try { map.putAll(m); } finally { w.unlock(); } } /** * */ public V remove(Object key) { w.lock(); try { return map.remove(key); } finally { w.unlock(); } } /** * */ public int size() { r.lock(); try { return map.size(); } finally { r.unlock(); } } /** * */ public Collection<V> values() { r.lock(); try { return new ArrayList<V>(map.values()); } finally { r.unlock(); } } }
上面的并发Map我们主要用的读写锁,的读锁和写锁分别控制并发Map的存和取。
ReadWriteLock需要严格区分读写操作,如果读操作使用了写入锁,那么降低读操作的吞吐量,如果写操作使用了读取锁,那么就可能发生数据错误。另外ReentrantReadWriteLock还有以下几个特性:
• 公平性
非公平锁(默认) 这个和独占锁的非公平性一样,由于读线程之间没有锁竞争,所以读操作没有公平性和非公平性,写操作时,由于写操作可能立即获取到锁,所以会推迟一个或多个读操作或者写操作。因此非公平锁的吞吐量要高于公平锁。公平锁 利用AQS的CLH队列,释放当前保持的锁(读锁或者写锁)时,优先为等待时间最长的那个写线程分配写入锁,当前前提是写线程的等待时间要比所有读线程的等待时间要长。同样一个线程持有写入锁或者有一个写线程已经在等待了,那么试图获取公平锁的(非重入)所有线程(包括读写线程)都将被阻塞,
直到最先的写线程释放锁。如果读线程的等待时间比写线程的等待时间还有长,那么一旦上一个写线程释放锁,这一组读线程将获取锁。
• 重入性
读写锁允许读线程和写线程按照请求锁的顺序重新获取读取锁或者写入锁。当然了只有写线程释放了锁,读线程才能获取重入锁。写线程获取写入锁后可以再次获取读取锁,但是读线程获取读取锁后却不能获取写入锁。另外读写锁最多支持65535个递归写入锁和65535个递归读取锁。
• 锁降级
写线程获取写入锁后可以获取读取锁,然后释放写入锁,这样就从写入锁变成了读取锁,从而实现锁降级的特性。
• 锁升级
读取锁是不能直接升级为写入锁的。因为获取一个写入锁需要释放所有读取锁,所以如果有两个读取锁尝试获取写入锁而都不释放读取锁时就会发生死锁。
• 锁获取中断
读取锁和写入锁都支持获取锁期间被中断。这个和独占锁一致。
• 条件变量
写入锁提供了条件变量(Condition)的支持,这个和独占锁一致,但是读取锁却不允许获取条件变量,将得到一个UnsupportedOperationException异常。
• 重入数
读取锁和写入锁的数量最大分别只能是65535(包括重入数)。
发表评论
-
Executors解析
2017-04-07 14:38 1245ThreadPoolExecutor解析一(核心线程池数量、线 ... -
ScheduledThreadPoolExecutor解析三(关闭线程池)
2017-04-06 20:52 4451ScheduledThreadPoolExecutor解析一( ... -
ScheduledThreadPoolExecutor解析二(任务调度)
2017-04-06 12:56 2117ScheduledThreadPoolExecutor解析一( ... -
ScheduledThreadPoolExecutor解析一(调度任务,任务队列)
2017-04-04 22:59 4986Executor接口的定义:http://donald-dra ... -
ThreadPoolExecutor解析四(线程池关闭)
2017-04-03 23:02 9098Executor接口的定义:http: ... -
ThreadPoolExecutor解析三(线程池执行提交任务)
2017-04-03 12:06 6080Executor接口的定义:http://donald-dra ... -
ThreadPoolExecutor解析二(线程工厂、工作线程,拒绝策略等)
2017-04-01 17:12 3036Executor接口的定义:http://donald-dra ... -
ThreadPoolExecutor解析一(核心线程池数量、线程池状态等)
2017-03-31 22:01 20514Executor接口的定义:http://donald-dra ... -
ScheduledExecutorService接口定义
2017-03-29 12:53 1502Executor接口的定义:http://donald-dra ... -
AbstractExecutorService解析
2017-03-29 08:27 1071Executor接口的定义:http: ... -
ExecutorCompletionService解析
2017-03-28 14:27 1586Executor接口的定义:http://donald-dra ... -
CompletionService接口定义
2017-03-28 12:39 1061Executor接口的定义:http://donald-dra ... -
FutureTask解析
2017-03-27 12:59 1324package java.util.concurrent; ... -
Future接口定义
2017-03-26 09:40 1193/* * Written by Doug Lea with ... -
ExecutorService接口定义
2017-03-25 22:14 1159Executor接口的定义:http://donald-dra ... -
Executor接口的定义
2017-03-24 23:24 1672package java.util.concurrent; ... -
简单测试线程池拒绝执行任务策略
2017-03-24 22:37 2025线程池多余任务的拒绝执行策略有四中,分别是直接丢弃任务Disc ... -
JAVA集合类简单综述
2017-03-23 22:51 920Queue接口定义:http://donald-draper. ... -
DelayQueue解析
2017-03-23 11:00 1733Queue接口定义:http://donald-draper. ... -
SynchronousQueue解析下-TransferQueue
2017-03-22 22:20 2133Queue接口定义:http://donald-draper. ...
相关推荐
10. 并发 Map(映射) ConcurrentMap 11. 并发导航映射 ConcurrentNavigableMap 12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. ...
并发 Map(映射) ConcurrentMap 11. 并发导航 映射 ConcurrentNavigableMap 12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. ...
链阻塞双端队列 LinkedBlockingDeque,并发 Map(映射) ConcurrentMap, 并发导航映射 ConcurrentNavigableMap,交换机 Exchanger, 信号量 Semaphore,执行器服务 ExecutorService, 线程池执行者 ThreadPoolExecutor,...
10. 并发 Map(映射) ConcurrentMap 11. 并发导航映射 ConcurrentNavigableMap 12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. ...
10. 并发 Map(映射) ConcurrentMap 11. 并发导航映射 ConcurrentNavigableMap 12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. ...
在Java中,除了内置的`synchronized`关键字之外,`java.util.concurrent.locks`包还提供了更灵活的锁实现,包括: ##### 3.1 Lock & ReentrantLock `Lock`接口提供了比`synchronized`更强大的锁定机制,它允许显式...
10. 并发 Map(映射) ConcurrentMap 11. 并发导航映射 ConcurrentNavigableMap 12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. ...
原子变量和 `ConcurrentMap` Java8 中的 `AtomicInteger`, `AtomicLong` 等类提供了一种无需显式锁定即可进行安全的整型变量更新的方式。同时,`ConcurrentHashMap` 的改进使其成为高并发场景下更高效的选择。 ##...
`ConcurrentHashMap`是`Map`接口的一种实现,它在多线程环境下具有高吞吐量,并且保证了一致性。相比于传统的`HashMap`,`ConcurrentHashMap`在并发环境下更为安全,因为它允许并发读取和一定程度上的并发修改。 - ...
- `java.util.concurrent.Lock`接口提供了更细粒度的锁机制,可以实现线程安全。 - `ReadWriteLock`允许多个读操作并发,但在写操作时会独占资源,确保线程安全。 3. **Java泛型**: - 泛型是Java 1.5引入的新...
2. `java.util.concurrent.locks`包:提供了更细粒度的锁,如`ReentrantLock`、`ReadWriteLock`等,允许更灵活的控制和更高的并发性。 3. `volatile`关键字:保证了变量的可见性和有序性,但不保证原子性。适合于...
Java并发编程是Java开发中的重要领域,而JUC(Java Util Concurrency)是Java平台提供的一套强大且全面的并发工具包,它位于`java.util.concurrent`包下。JUC为开发者提供了高效、线程安全的组件,使得多线程编程...
- **Lock接口**:Java.util.concurrent.locks包下的Lock接口提供了更灵活的线程同步方式,如ReentrantLock(可重入锁)、ReadWriteLock(读写锁)等。相比synchronized,Lock提供了更细粒度的控制,支持尝试获取锁...