看好了,我只表演一次
```java
/**
* ReadWriteLock读写锁
*
* ReadWriteLock是JDK5中提供的读写分离锁。读写分离锁可以有效地帮助减少锁竞争,以提升系统性能。
* 用锁分离的机制来提升性能非常容易理解,
* 比如线程A1、A2、A3进行写操作,B1、B2、B3进行读操作,
* 如果使用重入锁或者内部锁,则理论上说所有读之间、读与写之间、写和写之间都是串行操作。
* 当B1进行读取时,B2、B3则需要等待锁。由于读操作并不对数据的完整性造成破坏,这种等待显然是不合理的。
* 因此,读写锁就有了发挥功能的余地。
*
* 在这种情况下,读写锁运行多个线程同时读。
* 但是考虑到数据完整性,写写操作和读写操作间依然是需要互相等待和持有锁的。
* 总的来说,读写锁的访问约束如下表。
* 读 写
* 读 非阻塞 阻塞
* 写 阻塞 阻塞
*
* 如果在系统中,读的次数远远大于写的操作,读写锁就可以发挥最大的功效,提升系统的性能。
*
*/
public class ReadWriteLockExample {
/**
* 在读锁和写锁之间的交互可以采用多种实现方式。ReadWriteLock中的一些可选实现包括:
*
* 释放优先:当一个写入操作释放写入锁时,并且队列中同时存在读线程和写线程,那么应该优先选择哪一个线程。
* 读线程插队:如果锁是由读线程持有,但是写线程还在等待,是否允许新到的读线程获得访问权,还是应在写线程后面等待?
* 若允许的话可以提高并发性但是可能造成写线程的饥饿。
* 重入性:读取锁和写入锁是否可重入。
* 降级和升级:若一个线程持有写锁可否在继续持有写锁的状态下获取读锁?
* 这可能会使写锁“降级”为读锁。读锁是否优先于其它正在等待的读线程和写线程而升级为一个写锁?
* 在大多数读写锁实现中不支持“升级”,因为这样容易死锁(两个读线程试图同时升级为写锁,那么二者都不会释放写锁)。
*/
//创建普通重入锁
private static Lock lock = new ReentrantLock();
//创建读写分离锁
private static ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
//创建读锁
private static Lock readLock = rwlock.readLock();
//创建写锁
private static Lock writeLock = rwlock.writeLock();
private int value;
public Object HandleRead(Lock lock) throws InterruptedException {
try {
//上锁
lock.lock();
//模拟处理业务
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " Read...");
return value;
} finally {
//释放锁
lock.unlock();
}
}
public void HandleWrite(Lock lock,int index) throws InterruptedException {
try {
lock.lock();
Thread.sleep(1000);
value = index;
System.out.println(Thread.currentThread().getName() + " Write...");
}finally {
lock.unlock();
}
}
public static void main(String[] a ) throws InterruptedException {
final ReadWriteLockExample rwle = new ReadWriteLockExample();
//创建读方法
Runnable readR = new Runnable() {
@Override
public void run() {
try {
//rwle.HandleRead(lock); //普通锁
rwle.HandleRead(readLock);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//创建写方法
Runnable writeR = new Runnable() {
@Override
public void run() {
try {
//rwle.HandleWrite(lock,new Random().nextInt()); //普通锁
rwle.HandleWrite(writeLock,new Random().nextInt());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//18次读
for (int i=0;i<18;i++){
Thread s = new Thread(readR);
s.start();
}
//2次写
for (int i=18;i<20;i++){
Thread s = new Thread(writeR);
s.start();
}
/**
* 结论:
*
* 用普通锁运行,大约执行20秒左右
*
* 用读写分离锁,大约执行3秒左右
*
*/
}
}