ReentrantReadWriteLock此类不会将读取者优先或写入者优先强加给锁访问的排序。但是,它确实支持可选的公平 策略。
非公平模式(默认)
当非公平地(默认)构造时,未指定进入读写锁的顺序,受到 reentrancy 约束的限制。连续竞争的非公平锁可能无限期地推迟一个或多个 reader 或 writer 线程,但吞吐量通常要高于公平锁。
公平模式
当公平地构造线程时,线程利用一个近似到达顺序的策略来争夺进入。当释放当前保持的锁时,可以为等待时间最长的单个 writer 线程分配写入锁,如果有一组等待时间大于所有正在等待的 writer 线程 的 reader 线程,将为该组分配写入锁。
如果保持写入锁,或者有一个等待的 writer 线程,则试图获得公平读取锁(非重入地)的线程将会阻塞。直到当前最旧的等待 writer 线程已获得并释放了写入锁之后,该线程才会获得读取锁。当然,如果等待 writer 放弃其等待,而保留一个或更多 reader 线程为队列中带有写入锁自由的时间最长的 waiter,则将为那些 reader 分配读取锁。
试图获得公平写入锁的(非重入地)的线程将会阻塞,除非读取锁和写入锁都自由(这意味着没有等待线程)。(注意,非阻塞 ReentrantReadWriteLock.ReadLock.tryLock() 和 ReentrantReadWriteLock.WriteLock.tryLock() 方法不会遵守此公平设置,并将获得锁(如果可能),不考虑等待线程)。
package com.lifei11_27.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 读锁实现账户的存取
*
* @author Adil
*
*/
public class ReadLockTest {
public static void main(String[] args) {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
ReadLock inMoney = new ReadLock("悟空", 0, 1000, lock);
ReadLock outMoney = new ReadLock("空空", 2000, 0, lock);
inMoney.start();
try {
Thread.sleep(2000);
outMoney.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ReadLock extends Thread {
static int money = 500;// 预存500元
private ReentrantReadWriteLock lock;
private int outMoney;// 取钱
private int inMoney;// 存钱
private String userName;
public ReadLock() {
// TODO Auto-generated constructor stub
}
public ReadLock(String userName, int outMonye, int inMoney, ReentrantReadWriteLock lock) {
this.userName = userName;
this.outMoney = outMonye;
this.inMoney = inMoney;
this.lock = lock;
}
@Override
public void run() {
if (inMoney > 0) {
lock.writeLock().lock();
System.out.println(userName + "开始存钱,本次存钱金额为:" + inMoney);
try {
this.sleep(1000);
money += inMoney;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("存钱成功,余额为:" + money);
lock.writeLock().unlock();
}
if (outMoney > 0) {
lock.readLock().lock();
System.out.println(userName + "开始取钱,本次取款金额为:" + outMoney);
if(outMoney<=money){
try {
this.sleep(1000);
money -= outMoney;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("取钱成功,余额为:" + money);
}else{
System.out.println("对不起 您的账户余额不足");
}
lock.readLock().unlock();
}
}
}