读写锁

Posted toov5

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了读写锁相关的知识,希望对你有一定的参考价值。

相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题。Java5在java.util.concurrent包中已经包含了读写锁。尽管如此,我们还是应该了解其实现背后的原理。

 读 写 这种的 可以用wait  notify 之前已经实现过了  读的时候不能写 写的时候不能做 保证共性的全局变量安全

下面,先来写个读写锁大家看看:

package com.toov5.readAndWriteLock;

import java.util.HashMap;
import java.util.Map;

//读写锁 类似jvm内置缓存(把值存到jvm中)
public class writeAndReadLock {
    private volatile Map<Object,Object> cache = new HashMap<>();  
    
    //写入元素
    public void put(String key,String value){
        try {
            Thread.sleep(500);
            System.out.println("写入"+key+value);
            cache.put(key, value);
            System.out.println("写入"+key+value+"结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    //读取元素
    public String get(String key){
        try {
            Thread.sleep(500);
            System.out.println("读取"+key);
            String result = cache.get(key).toString();
            System.out.println("读取"+key+"结束");
            return result;
        } catch (Exception e) {
            return null;
        }
    }
    
     public static void main(String[] args) {
        writeAndReadLock lock = new writeAndReadLock();
        //写线程
          Thread t1 = new Thread(new Runnable() {    
            @Override
            public void run() {
                for(int i =0; i<10;i++){
                    lock.put("i", i+"");
                }
            }
        });
          
      //读线程      
          Thread t2 = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    for(int i=0; i<10;i++){
                        lock.get(i+"");
                    }
                }
            }); 
      t1.start();
      t2.start();
          
    }
    
}

结果:

技术分享图片

 

如果两个方法都加上synchronize 那么读的时候 不能写 写的时候不能读

下面提供读写锁:

package com.toov5.readAndWriteLock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

//读写锁 类似jvm内置缓存(把值存到jvm中)
public class writeAndReadLock {
    private volatile Map<Object,Object> cache = new HashMap<>();  
    private ReentrantReadWriteLock wrl = new ReentrantReadWriteLock();  
    private WriteLock wirtelock=wrl.writeLock();//获取到写锁
    private ReadLock readLock =wrl.readLock(); //获取到读锁
    //写入元素
    public void put(String key,String value){
        try {    
            wirtelock.lock();
            Thread.sleep(500);
            System.out.println("写入"+key+value);
            cache.put(key, value);
            System.out.println("写入"+key+value+"结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            wirtelock.unlock();
        }
    }
    
    //读取元素
    public String get(String key){
        try {
            readLock.lock();
            Thread.sleep(500);
            System.out.println("读取"+key);
            String result = cache.get(key).toString();
            System.out.println("读取"+key+"结束");
            return result;
        } catch (Exception e) {
            return null;
        }finally{
            readLock.unlock();
        }
    }
    
     public static void main(String[] args) {
        writeAndReadLock lock = new writeAndReadLock();
        //写线程
          Thread t1 = new Thread(new Runnable() {    
            @Override
            public void run() {
                for(int i =0; i<10;i++){
                    lock.put("i", i+"");
                }
            }
        });
          
      //读线程      
          Thread t2 = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    for(int i=0; i<10;i++){
                        lock.get(i+"");
                    }
                }
            }); 
      t1.start();
      t2.start();
          
    }
    
}

技术分享图片

没有写完时候 是不能读的

看源码:

技术分享图片

与之前的lock锁不一样之前是 reentrantlock,它有读和写两把锁

 两个线程同时写,同时读是不可能的。不共存! 

读读 可以 读写不可共存  写写不可以共存

 

以上是关于读写锁的主要内容,如果未能解决你的问题,请参考以下文章

互斥锁自旋锁读写锁和条件变量

ReentrantReadWriteLock场景应用

读写锁ReentrantReadWriteLock源代码浅析

锁,同步,可重入锁,读写锁(转)

我写的由 GCD 代码支持的读写器锁导致并行测试中的死锁

读写锁(ReadWriteLock)