多线程与锁(十五)之 读锁与写锁

读锁:共享锁:会发生死锁

       死锁情况:有两个线程A和线程B,都要对一条数据进行读取并修改,而线程A要修改必须要等线程B读完之后进行,同样线程B要修改必须要等待线程A读完之后进行,此时会发生死锁。

写锁:独占锁:会发生死锁

      死锁情况:有两个线程线程A和线程B,同时有两条数据,数据1和数据2,线程A要对数据1和数据2进行修改,线程B要对数据2和数据1进行修改,但A要等B对数据2修改完之后才能修改数据2,B要等A对数据1修改完之后才能修改数据1,此时发生互相等待,故会造成死锁

读写锁:一个资源可以被多个读线程访问,或者可以被一个写线程访问,但是不能同时存在读写线程,读写互斥,读读共享

缺点:1.造成锁饥饿,一直读,没有写操作

           2.读时候,不能写,只有读完之后,才可以写,写操作可以读

/**
 * @author
 * @date 2022/12/28 21:17
 * 读写锁演示
 */

//资源类
class MyCache{

    //创建map集合
    private volatile Map<String,Object> map= new HashMap<>();
    //创建读写锁对象
     private ReadWriteLock rwLock = new ReentrantReadWriteLock();
    //写数据
    public void put(String key,Object value) {
        //添加写锁
        rwLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"正在写操作"+key);
            //暂停一会
            TimeUnit.MICROSECONDS.sleep(300);
            //放数据
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"写完了"+key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            //释放锁
            rwLock.writeLock().unlock();
        }

    }
    //取数据
    public Object get(String key){
        //添加读锁
        rwLock.readLock().lock();
        Object result = null;
        try {
            System.out.println(Thread.currentThread().getName()+"正在进行读操作"+key);
            TimeUnit.MICROSECONDS.sleep(300);
            result = map.get(key);
            System.out.println(Thread.currentThread().getName()+"取完了"+key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放锁
            rwLock.readLock().unlock();
        }
        return result;
    }
}
public class ReadWriteDemo {

    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        //创建线程放数据
        for (int i = 1; i <= 5 ; i++) {
            final int num = i;
            new Thread(()->{
                myCache.put(num+"",num+"");
            },String.valueOf(i)).start();
        }
        //创建线程取数据
        for (int i = 1; i <= 5 ; i++) {
            final int num = i;
            new Thread(()->{
                myCache.get(num+"");
            },String.valueOf(i)).start();
        }
    }
}

 解释:从以上代码演示结果可以看到,写锁是独占的形式一个执行完之后另一个才可以执行,而读锁是共享的形式,多个线程可以同时进行。

锁降级:

/**
 * @author
 * @date 2022/12/29 21:41
 *读写锁降级演示
 */
public class ReadWriteLockDemoteDemo {

    public static void main(String[] args) {
        //创建一个读写锁
        ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
        //创建一个读锁
        ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
        //创建一个写锁
        ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();

        //锁降级
        writeLock.lock();
        System.out.println("写操作");

        readLock.lock();
        System.out.println("读操作");
        //释放写锁
        writeLock.unlock();
        
        //释放读锁
        readLock.unlock();
       

    }
}

解释:就是写时可读,读时不可以写;就像数据库的增删改与查询一样,增删改之前需要查找到相关数据才可以对相关数据进行操作,而查询时不可以对相关数据进行修改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值