如何优化读多写少的场景
读写锁原则
允许多个线程同时读共享变量; 只允许一个线程写共享变量; 如果一个写线程正在执行写操作,此时禁止读线程读共享变量。
不支持从读锁到写锁的升级,反之支持。
锁升级测试
结论
支持写锁重入: 写锁后再加写锁,可以运行结束 支持读锁重入:读锁后再加读锁,可以运行结束 支持降级:先加写锁 再加读锁可以运行结束(🤔🤔🤔)
不支持升级:先加读锁 再加写锁可以运行结束(🤔🤔🤔)
public static void main(String[] args) {PaymentServiceImpl p = new PaymentServiceImpl();p.test();}public void test(){r.lock();try{System.out.println("进入读锁");w.lock();try{Thread.sleep(1000);System.out.println("进入写锁");}finally {w.lock();}} catch (InterruptedException e) {e.printStackTrace();} finally {r.unlock();}System.out.println("执行完毕");}
课后思考
有同学反映线上系统停止响应了,CPU 利用率很低,你怀疑有同学一不小心写出了读锁升级写锁的方案,那你该如何验证自己的怀疑呢?
答案
后记
java 中的读写锁类似mysql中的lock in share mode (select from test where id = 1 lock in share mode;)
for update 是读读互斥,读写互斥(select from test where id = 1 for update)
