上一篇讲到ReentrantLock是排他性,一方面保证了线程的绝对安全,但另一方面降低了效率。对于一些不需要操作实例变量的方法中,有另外一种锁可以提高运行效率,这种锁就是ReadWriteReentrantLock。
ReentrantReadWriteLock,也称为读写锁。读写锁有两个锁,一个是读操作相关的锁,也叫共享锁;另一个是写操作相关锁,也叫排他锁。
读锁之间不互斥,写锁之间互斥,读写锁之间互斥。
使用
private ReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
.
.
.
lock.readLock().unlock();
lock.writeLock().lock();
.
.
.
lock.writeLock().unlock();
举个具体例子:
1、创建服务类
package com.cjs.ReadWriteLock_3;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Service {
private ReadWriteLock lock = new ReentrantReadWriteLock();
public void read() {
try {
try {
lock.readLock().lock();
System.out.println("获得读锁:" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
Thread.sleep(3000);
} finally {
lock.readLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void write() {
try {
try {
lock.writeLock().lock();
System.out.println("获得写锁:" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
Thread.sleep(3000);
} finally {
lock.writeLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、创建两个线程类,
package com.cjs.ReadWriteLock_3;
public class ReadThread extends Thread {
private Service service;
@Override
public void run() {
service.read();
}
public ReadThread(Service service) {
this.service = service;
}
}
package com.cjs.ReadWriteLock_3;
public class WriteThread extends Thread {
private Service service;
public WriteThread(Service service) {
this.service = service;
}
@Override
public void run() {
service.write();
}
}
3、创建一个Main类,
package com.cjs.ReadWriteLock_3;
public class Run {
public static void main(String[] args) {
Service service = new Service();
ReadThread[] readThreads = new ReadThread[10];
WriteThread[] writeThreads = new WriteThread[10];
for (int i = 0; i < 10; i++) {
readThreads[i] = new ReadThread(service);
readThreads[i].setName("ReadThread" + (i + 1));
readThreads[i].start();
writeThreads[i] = new WriteThread(service);
writeThreads[i].setName("WriteThread" + (i + 1));
writeThreads[i].start();
}
}
}
4、运行程序,
注意框框的两条记录,上面提及的读写锁之间的两两特性,只有当当前持有写锁时,其他线程才会进入阻塞状态,如果是持有读锁,那么还是会有可能另一个线程获得读锁。