在多线程中,为了提高效率有些共享资源允许同时进行多个读的操作,但只允许一个写的操作,比如一个文件,只要其内容不变可以让多个线程同时读,不必做排他的锁定,排他的锁定只有在写的时候需要,以保证别的线程不会看到数据不完整的文件。这时候就需要使用读写锁。
-
-
-
-
-
- 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(10000));
- }
- }
-
- }.start();
-
- }
-
- }
- }
-
- class Queue3{
- private Object data = null;
-
- 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 (InterruptedException 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 (InterruptedException e) {
- e.printStackTrace();
- }finally{
- rwl.writeLock().unlock();
- }
-
-
- }
- }
运行结果:
Thread-0 be ready to readdata!
Thread-2 be ready to readdata!
Thread-2have read data:null
Thread-0have read data:null
Thread-1 be ready towrite data!
Thread-1 have write data:1021
Thread-1 be ready towrite data!
Thread-1 have write data:2887
看到这里不免有人会问,既然读的时候可以多人访问,那么为什么还要加读锁呢?
答:当然要加锁了,否则在写时去读,可能不正确-(写的时候不能去读)
读写锁-模拟缓存系统实现:
- 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 = "aaaa";
- }
- }finally{
-
- rwl.writeLock().unlock();
- }
- rwl.readLock().lock();
- }
- }finally{
- rwl.readLock().unlock();
- }
- return value;
- }
- }
总结:
读写锁的作用为,当我们加上写锁时,其他线程被阻塞,只有一个写操作在执行,当我们加上读锁后,它是不会限制多个读线程去访问的。也就是get和put之间是互斥的,put与任何线程均为互斥,但是get与get线程间并不是互斥的。其实加读写锁的目的是同一把锁的读锁既可以与写锁互斥,读锁之间还可以共享。