java线程:互斥锁与读写锁
来源:互联网 发布:网络信息收集步骤 编辑:程序博客网 时间:2024/05/16 12:09
两种互斥锁机制:
1、synchronized
2、ReentrantLock
ReentrantLock是jdk5的新特性,采用ReentrantLock可以完全替代替换synchronized传统的锁机制,而且采用ReentrantLock的方式更加面向对象,也更加灵活,网上有很多关于对比两者锁方式的文章,这里就不多口舌了,大家baidu、google一下就水落石出了。在本博客中也写关于这两种锁方式实现的经典例子《生产者消费者》。
关于读写锁,用语言解释不如直接用代码诠释,以下通过两个例子讲述读写锁以及读写锁的使用:
1、synchronized
2、ReentrantLock
ReentrantLock是jdk5的新特性,采用ReentrantLock可以完全替代替换synchronized传统的锁机制,而且采用ReentrantLock的方式更加面向对象,也更加灵活,网上有很多关于对比两者锁方式的文章,这里就不多口舌了,大家baidu、google一下就水落石出了。在本博客中也写关于这两种锁方式实现的经典例子《生产者消费者》。
关于读写锁,用语言解释不如直接用代码诠释,以下通过两个例子讲述读写锁以及读写锁的使用:
例子1:
import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author amber2012 * * 读写锁:ReadWriteLock * * 在多线程的环境下,对同一份数据进行读写,会涉及到线程安全的问题。比如在一个线程读取数据的时候,另外一个线程在 * 写数据,而导致前后数据的不一致性;一个线程在写数据的时候,另一个线程也在写,同样也会导致线程前后看到的数据的 * 不一致性。 * * 这时候可以在读写方法中加入互斥锁,任何时候只能允许一个线程的一个读或写操作,而不允许其他线程的读或写操作,这 * 样是可以解决这样以上的问题,但是效率却大打折扣了。因为在真实的业务场景中,一份数据,读取数据的操作次数通常高 * 于写入数据的操作,而线程与线程间的读读操作是不涉及到线程安全的问题,没有必要加入互斥锁,只要在读-写,写-写期 * 间上锁就行了。 * * 对于这种情况,读写锁则最好的解决方案! * * 读写锁的机制: * "读-读"不互斥 * "读-写"互斥 * "写-写"互斥 * * 即在任何时候必须保证: * 只有一个线程在写入; * 线程正在读取的时候,写入操作等待; * 线程正在写入的时候,其他线程的写入操作和读取操作都要等待; * * 以下是一个缓存类:用于演示读写锁的操作:重入、降级 */ 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; } }
例子2:
import java.util.Map; import java.util.TreeMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.xml.crypto.Data; /** * @author amber2012 * * jdk文档中关于ReentrantReadWriteLock类使用的一个很好的例子,以下是具体的介绍: * * 在使用某些种类的 Collection 时,可以使用 ReentrantReadWriteLock 来提高并发性。通常,在预期 collection * 很大,读取者线程访问它的次数多于写入者线程,并且 entail 操作的开销高于同步开销时,这很值得一试。例如,以下 * 是一个使用 TreeMap 的类,预期它很大,并且能被同时访问。 */ public class RWDictionary { private final Map<String, Data> map = new TreeMap<String, Data>(); private final ReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock readLock = rwl.readLock(); private final Lock writeLock = rwl.writeLock(); public Data 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 Data put(String key, Data value) { writeLock.lock(); try { return map.put(key, value); } finally { writeLock.unlock(); } } public void clear() { writeLock.lock(); try { map.clear(); } finally { writeLock.unlock(); } } }
0 0
- java线程:互斥锁与读写锁
- java线程:互斥锁与读写锁
- java线程:互斥锁与读写锁
- 10066--- java线程:互斥锁与读写锁
- JAVA线程读写锁与线程之间通信例子
- 线程与读写锁
- java 线程读写锁
- Java--线程--线程控制,线程安全,线程同步,线程等待,线程交互,死锁,互斥锁,读写锁
- Java--线程--线程控制,线程安全,线程同步,线程等待,线程交互,死锁,互斥锁,读写锁
- Java线程(四):JUC包线程互斥与同步以及读写锁
- 线程互斥——互斥锁与读写锁
- Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁
- 线程同步与互斥:读写锁
- 线程同步与互斥:读写锁
- java 之 读写锁 线程间互斥
- java线程系列---读写锁ReentrantReadWriteLock
- java 线程 ReadWriteLock 读写锁的使用
- 【Java多线程与并发库】10.java5的线程锁(读写锁)技术
- 【赚取智能手环】PHP开发学习门户有奖答题活动火热进行中!
- 如何高效利用GitHub
- itunes 歌曲导出 和上传
- myBatis批量添加,修改和删除
- 第五章函数—5.1.2讲学习笔记
- java线程:互斥锁与读写锁
- 启用Windows 8的Administrator账户
- openwrt 编译环境搭建及Makefile
- 人气斑竹老狼的故事
- 名片中头衔的英语称呼翻译
- 第13周项目6体验文件操作(1)预备
- 第十一周项目三(4) 递归返回Fibnacci数列的第n个数
- 何必向不值得的人证明什么,生活得更好,是为了自己
- Visual Basic 通过PID获取进程文件路径