读写所概念
我们平常通过锁来对进程进行协同。
但如果在读多写少的场景(可以允许多个读同时进行不影响)也使用普通的锁,会严重影响程序的性能。
为了解决这个问题引入读写锁,请看下面场景1:
1.读线程:如果thread在写resource的时候,其他read和write线程都终止。
2.写线程:可以允许多个thread同时读取resource。
我们先澄清一下定义和规则:
a.如果一个线程是读取资源就叫读线程,如果是写资源就叫写线程。
b.为了实现上面的“场景1”的要求,在代码中我们需要在读操作加上read锁,在写操作加上write锁。
读写所机制伪代码讲解
ReadWriteLock wrLock = new ReentrantReadWriteLock();
read线程执行获取读锁:
get(){
wrlock.getReadLock.lock();
...println(Thread.currentThread().getName() + " 准备读数据!");
/* 休眠 */
...println(Thread.currentThread().getName() + "读取完毕 :" + data);
wrlock.getReadLock.unlock();
}
write线程执行获取写锁:
put(){
wrlock.getWriteLock.lock();
...println(Thread.currentThread().getName() + " 准备写入数据!");
/* 休眠 */
...println(Thread.currentThread().getName() + "写入完毕");
wrlock.getWriteLock.unlock();
}
运行结果为:
/*******a b 两个线程同时执行*****/
a准备读取数据
b准备读取数据
a读取完毕
b读取完毕
/一次只有一个写线程,所以先c执行再d执行*/
// c线程执行
c准备写入数据!
c写入完毕
// d线程执行
d准备写入数据!
d写入完毕
如何使用
加锁是使其资源原子性,不管其资源是内存还是数据库。
我们并发控制的是资源不是代码?比如如下代码如何协同:
A: code1 code2
B: code1 code2
想象执行序列:
a).A,B线程都执行到code1 :A :code1 B:code1。
b).A执行到code1,B执行到code2。
不管执行序列如何,我们必须通过同一个lock对象来协同线程的访问。
在该排他代码的地方加 write锁,在非排他地方加read锁。
参考
http://tutorials.jenkov.com/java-concurrency/read-write-locks.html