什么是共享锁和排他锁
- 排他锁:也称独占锁、独享锁
排他锁顾名思义,就是是一个自私的锁,当一个线程获取锁之后,只有当前线程可以进行修改和读取。
- 共享锁:也称读锁
同样顾名思义,共享锁是一个有爱的锁,愿意与人分享。当一个线程获取共享锁之后,其他线程也可以来拿共享锁,但是获取共享锁只能用来读取数据不能修改数据。(注:为什么可以多读,不能写?这涉及到线程安全问题,线程安全的产生就是发生在修改数据时,主要因为一个线程修改数据而别的线程没有获取到最新的数据而业务发生错误,具体的理解要通过JMM模型以及线程安全3大特性)
在Java中ReentrantReadWriteLock(俗称读写锁)是共享锁和排他锁同时具备的工具类,在业务合适时,可以通过合适的时机采用读锁来节省资源。
为什么要有读写锁?
没有读写锁之前,我们都是使用排他锁,如:ReentrantLock。虽然排它锁已经完全可以保证线程的安全了,让程序能够顺畅的运行。但是加排它锁,意味着加锁业务只能单线程执行,那么性能也随之下降。可是当前业务可能很少的时候需要多线程写,大多数时候是进行读,而多线程读是不会产生安全问题的,那么总是单线程执行不就浪费很多资源嘛!
加锁效率低,不加锁有时又不安全,那到底加锁还是不加锁?小孩子才做选择,成年人都要!所以就有了读写锁的产生。
读写锁的原则
- 多个线程只申请读锁,都可以申请到
- 如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。
- 如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程会一直等待释放写锁
- 一句话总结:要么是一个或多个线程同时有读锁,要么是一个线程有写锁,但是两者不会同时出现