1、科普定义java
这篇博文的两个主角“synchronized”和“读写锁”面试
1)synchronized数据库
这个同步关键字相信你们都用得比较多,在上一篇“多个线程之间共享数据的方式”中也详细列举他的应用,在这就很少说只作几点概括:编程
2)读写锁缓存
咱们对数据的操做无非两种:“读”和“写”,试想一个这样的情景,当十个线程同时读取某个数据时,这个操做应不该该加同步。答案是不必的。只有如下两种状况须要加同步:多线程
因此性能
java5提供了读写锁这种锁支持多线程读操做不互斥,多线程读写互斥,多线程写写互斥。读操做不互斥这样有助于性能的提升,这点在java5之前没有优化
二.用一道面试题来具体比较这两点ui
题目:“白板编程,实现一个缓存系统”spa
题目分析:
对这个缓存系统的理解:
间于用户和数据库中间的一个环节,咱们知道用户直接访问数据库的时间是远大于直接访问内存,因此有了缓存区后用户访问数据时 这样,用户先访问缓存区当缓存区有用户须要的数据时直接拿走,当缓存区没有这样的数据,访问数据库并把访问所得的数据放在缓存区,这样当下一个须要这个数据的用户就直接访问内存便可获得。
核心代码实现:
首先用synchronized实现
public synchronized Object getData(String key){ Object result = map.get(key); if(result ==null){ result = "new";//用这步代替访问数据库得数据 } return result; }
用读写锁实现
public Object getData(String key){ rw.readLock().lock();//在读前先上读锁 Object result = null; try{ result = map.get(key); //这个if比较关键,它避免了多余的几回对数据哭的读取 if(result==null){ //若是内存中没有所要数据 rw.readLock().unlock(); rw.writeLock().lock(); if(result==null){ try{ //咱们用这个代替对数据库访问获得数据的步骤 result = "new"; }finally{ rw.writeLock().unlock(); } rw.readLock().lock(); } } }finally{ rw.readLock().unlock(); } return result; }
代码分析:
class CachedData { Object data; volatile boolean cacheValid; ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock(); <span style="color: #ff0000;">if (!cacheValid)</span> { // Must release read lock before acquiring write lock rwl.readLock().unlock(); rwl.writeLock().lock(); // Recheck state because another thread might have acquired // write lock and changed state before we did. <span style="color: #ff0000;"> if (!cacheValid)</span> { data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.readLock().lock(); rwl.writeLock().unlock(); // Unlock write, still hold read } use(data); rwl.readLock().unlock(); } }