高管触碰红线员工消失,读写锁模式(Read Write Pattern)来破谣

目的

维护一起请求读的一致性, 避免一起请求读取相同的数据但是得到不同的结果, 相比于互斥锁有更好的并发

例子代码

最近福报厂的价值观又上了热搜, 微博因为蒋某热榜停更一周, 一个 P8 也试图以权谋色, 重演绿地70后高管的套路, 然后被开除了, 二个相似的对比不禁让人感慨, 员工触犯红线, 员工消失, 高管触犯红线, 红线消失.

比如我们有这样一个存储结构里面有福报厂最近的大瓜可以吃

public class BadEventPool {

    public static final List<BadEvent> badEventList = new CopyOnWriteArrayList<>();

    public static String findNewBadEventPeopleName() {
        return badEventList.stream().max(Comparator.comparing(BadEvent::getHappenedTime))
            .orElse(new BadEvent()).getPeopleName();
    }

    public static String findNewBadEventName() {
        return badEventList.stream().max(Comparator.comparing(BadEvent::getHappenedTime))
            .orElse(new BadEvent()).getEventName();
    }
}

每个大瓜的结构如下:

@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
public class BadEvent {

    private String peopleName;

    private String eventName;

    private LocalDateTime happenedTime;
}

我们试图输出最新的大瓜:

Thread runnable = new Thread() {
    @Override
    public void run() {
        IntStream.range(0,100).forEach(
            (i) ->
            {
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                BadEvent p8 = new BadEvent("无名P8",
                    "对应聘人员语言骚扰, 触碰红线, 员工消失", LocalDateTime.now());
                BadEvent jf = new BadEvent("蒋某", "出轨网红, 触碰红线, 红线消失",
                    LocalDateTime.now());
                BadEvent badEvent = i < 50 ?
                    jf
                    : p8;
                //System.out.println(badEvent);
                BadEventPool.badEventList.add(badEvent);
            }
        );
    }
};
runnable.start();

sleep(2000);
String newBadPeopleName = BadEventPool.findNewBadEventPeopleName();
sleep(5000);
String newBadEventName = BadEventPool.findNewBadEventName();
System.out.println("result: " + newBadPeopleName + newBadEventName);

输出如下:

result: 蒋某对应聘人员语言骚扰, 触碰红线, 员工消失

问题分析

主要是一个线程在查询的过程中, 另外一个线程把最新的大瓜的变掉了, 所以导致了这个情况, 也是就数据库隔离级别中的可重复读类似的没有保证才会重现这种谣言.

读写锁模式

ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
ReadLock readLock = lock.readLock();
WriteLock writeLock = lock.writeLock();
Thread runnable = new Thread() {
    @Override
    public void run() {
        writeLock.lock();
        IntStream.range(0,100).forEach(
            (i) ->
            {
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                BadEvent p8 = new BadEvent("无名P8",
                    "对应聘人员语言骚扰, 触碰红线, 员工消失", LocalDateTime.now());
                BadEvent jf = new BadEvent("蒋凡", "出轨网红, 触碰红线, 红线消失",
                    LocalDateTime.now());
                BadEvent badEvent = i < 50 ?
                    jf
                    : p8;
                //System.out.println(badEvent);
                BadEventPool.badEventList.add(badEvent);
            }
        );
        writeLock.unlock();
    }
};
runnable.start();

sleep(2000);
readLock.lock();
String newBadPeopleName = BadEventPool.findNewBadEventPeopleName();
sleep(5000);
String newBadEventName = BadEventPool.findNewBadEventName();
readLock.unlock();
System.out.println("result: " + newBadPeopleName + newBadEventName);

输出结果如下:

result: 无名P8对应聘人员语言骚扰, 触碰红线, 员工消失

课后作业

  1. 将 jvm 锁改成分布式读写锁
  2. 使用 try-with-resource 方式实现读写锁的释放

微信公共号:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值