之前没真正使用读写锁,看到别人对读写锁的解释总感觉一头雾水。今天亲自敲代码实验之后,才明了,原来如此。网上没有一篇文章是能描述出自己理解的样子,所以将自己的思路记下来。先提出疑问,边自答边找思路,有了思路,再回头去运行一下代码,就清晰明了了。
如果你急着想要一句话概括读写锁,那我会告诉你:
读锁是加在读方法里的,是为了方便线程在运行写方法的时候阻止其他线程执行这个读方法,而没有写操作时读锁被忽略。
额,不知道我这么说会不会有人能理解,哈哈哈,如果不理解,可以看章末读写锁的执行图。
1.首先先提出疑问
- 为什么要区分读写?如果只有一种锁会是怎样?
自答:只有一种锁,那无论什么方法只要加锁了,就只能有一个线程可以进入。 - 但如果出现接下来说明的情况,简单锁效率就十分低,情况是这样的:
有个对象,可以对一个共有资源进行读写操作。读写都需要加锁吧?
自答:若不加锁那么写的时候读的结果就被影响了。嗯,所以加锁! - 当多个线程使用这个对象进行读操作,会是怎样?
每次进入读的代码时,都要等待获得锁。那这种等待是没有必要的。为了解决读操作的等待,特地区分了锁。
2.认识区分策略
写锁:当线程获得写锁时,其他所有准备进入加锁的线程(不管写锁还是读锁)都进入阻塞状态。
读锁:当线程获取读锁时,如果有线程在写,则进入阻塞状态,没有则可以进入执行。
3.边运行边感受
读写锁的执行图如下:
附上读写类的代码:
public class ReadWriteTest {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void read(){
try{
try{
lock.readLock().lock();
System.out.println("获得读锁" + Thread.currentThread().getName()
+ " " + System.currentTimeMillis());
Thread.sleep(1000 * 2);
System.out.println("结束读");
}finally {
lock.readLock().unlock();
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
public void write(){
try{
try{
lock.writeLock().lock();
System.out.println("获得写锁" + Thread.currentThread().getName()
+ " " + System.currentTimeMillis());
Thread.sleep(1000 * 2);
System.out.println("结束写");
}finally {
lock.writeLock().unlock();
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}