ReadWriteLock是读写锁,它解决了传统synchronized锁和Lock锁并发效率低的问题
ReadWriteLock的优点和解决的问题
我们都知道,在多线程并发的情况下要给资源类加锁,一个时间段只有一个线程能够访问该资源类的加锁操作,保证了数据的正确性。但是这也同时降低了并发性。写-写,读-写必须要加锁,而读-读是不需要加锁的,但synchronized锁和Lock锁把读-读也上了锁,这必然导致并发效率降低。
ReadWriteLock读写锁可以完美地解决以上的问题,对资源的”写“操作加上写锁,对“读”操作加上读锁,可以实现写-写,读-写独占,读-读共享。
ReadWriteLock读写锁既保证了数据的正确性又不会使并发性降低。
ReadWriteLock应用小demo
场景:有五个线程要对资源类执行”写入“操作,十个线程要对资源类执行“读取”操作
class Resource{
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void write() {
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "开始执行写入操作");
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行写入操作完毕");
} finally {
readWriteLock.writeLock().unlock();
}
}
public void read() {
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "开始执行读操作");
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行读操作完毕");
} finally {
readWriteLock.readLock().unlock();
}
}
}
public static void main(String[] args) {
Resource resource = new Resource();
//5个写入线程
for(int i = 0; i < 5; i++) {
new Thread(()->{
resource.write();
}, "写入线程" + (i + 1)).start();
}
//10个读线程
for(int i = 0; i < 10; i++) {
new Thread(()->{
resource.read();
}, "读线程" + (i + 1)).start();
}
}
执行结果:
写入线程2开始执行写入操作
写入线程2执行写入操作完毕
写入线程1开始执行写入操作
写入线程1执行写入操作完毕
写入线程3开始执行写入操作
写入线程3执行写入操作完毕
写入线程4开始执行写入操作
写入线程4执行写入操作完毕
写入线程5开始执行写入操作
写入线程5执行写入操作完毕
读线程2开始执行读操作
读线程1开始执行读操作
读线程3开始执行读操作
读线程6开始执行读操作
读线程4开始执行读操作
读线程7开始执行读操作
读线程5开始执行读操作
读线程8开始执行读操作
读线程10开始执行读操作
读线程9开始执行读操作
读线程2执行读操作完毕
读线程3执行读操作完毕
读线程1执行读操作完毕
从执行结果可以看到,“写”的过程是独占的,并不会被打断,而多个“读”线程可以同时共享“读”操作