heima并发25---并发工具包(4)---读写锁--247-252

ReentrantReadWriteLock。

两个线程的读操作是不涉及到修改的,我们可以读读的话是不加锁的。

锁的升级和降级:https://blog.csdn.net/aitangyong/article/details/38315885

重入的话锁是可以降级不可以升级的。

我们来演示下读写锁的使用方法。

 不管是什么锁,锁的本质是在方法里面加锁,而不是在线程里面加锁的。

代码:

package cn.itcast.n8;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.ReentrantReadWriteLock;

import static cn.itcast.n2.util.Sleeper.sleep;

@Slf4j(topic = "c.TestReadWriteLock")
public class TestReadWriteLock {
    public static void main(String[] args) throws InterruptedException {
        DataContainer dataContainer = new DataContainer();
        new Thread(() -> {
            dataContainer.read();
        }, "t1").start();

        new Thread(() -> {
            dataContainer.read();
        }, "t2").start();
    }
}

@Slf4j(topic = "c.DataContainer")
class DataContainer {
    private Object data;
    private ReentrantReadWriteLock rw = new ReentrantReadWriteLock();
    private ReentrantReadWriteLock.ReadLock r = rw.readLock();
    private ReentrantReadWriteLock.WriteLock w = rw.writeLock();

    public Object read() {
        System.out.println("get readlock...");
        r.lock();
        try {
            System.out.println("read");
            sleep(1);
            return data;
        } finally {
            System.out.println("relese read lock...");
            r.unlock();
        }
    }

    public void write() {
        System.out.println("get writelock...");
        w.lock();
        try {
            System.out.println("write");
            sleep(1);
        } finally {
            System.out.println("release writelock...");
            w.unlock();
        }
    }
}

---247---

读锁是不支持条件变量的,写锁是支持条件变量的。

重入的话是不支持升级的。

我们看下jdk自己带的锁的例子:


缓存在释放写锁的时候降级为读锁,这样别的线程就不能加写锁,可以让缓存快速的读取。

---248---

读写锁的应用----应用到缓存,保证缓存和数据库的一致性-----------------牛逼啊。

代码:

装饰器模式:https://www.runoob.com/design-pattern/decorator-pattern.html

我们只看重点的代码:最开始是这样写的。

这个是有问题的。

---249---

读取的时候就是读的是缓存缓存没有就读数据库再把数据放在缓存。

更新就是先清缓存,再更新数据库。

找问题:

我们想一下多线程的并发的问题。

清空缓存和更新数据库不加锁,导致不一致问题。

---

 

总结:先更新数据库,再清除缓存是合适的。

增加删除只是清除缓存 不更新缓存数据 查询更新缓存数据

强一致:加锁实现的。

总结:集合类不好 并发大所有的线程读取都会查数据库 先更新库再清空缓存

---250---

读写锁:既保证一致性,又不至于性能很低。

写操作加写锁,读操作加读锁,锁是加在方法上的,方法是线程调用的,下面找个缓存和数据库先后顺序就不重要了。

·

写加写锁。

读锁是如何加呢?

这里再做一次判断:

为什么?多个写阻塞了,释放之后就会再进来的。这个时候已经跳过判断了。

其实性能肯定有影响的。

---251---

补充:读多写少,查询多呢?

锁的细粒度,比如两个表读写不要用一把锁。

---252---

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值