使用独占锁最大的特点在于其只允许一个线程进行操作,这样在数据更新的时候可以保证操作的完整性.但是在进行数据读取时,独占锁会造成严重的性能问题,为了解决高并发下的快速访问与安全修改,JUC提供了ReentrantReadWriteLock读/写锁,即在读取的时候上读锁,在写入的时候上写锁.这两种锁是互斥的.由JVM进行控制.
在ReentrantReadWriteLock中,读锁属于共享锁.而写锁只允许一个线程进行操作…所以在使用时就需要通过不同的方式获取锁.
public class Account {
//账号名称
private String name;
//资产
private double asset;
//读写锁
private ReadWriteLock lock=new ReentrantReadWriteLock();
public Account(String name, double asset) {
this.name = name;
this.asset = asset;
}
/**
* 资产追加
* @param money
*/
public void saveMoney(double money){
//获取写锁(独占)
this.lock.writeLock().lock();
try {
this.asset += money;
System.out.println(Thread.currentThread().getName()+"修改银行账户数据:"+money+";当前资产:"+this.asset);
} catch (Exception e) {
e.printStackTrace();
}finally {
//释放写锁
this.lock.writeLock().unlock();
}
}
/**
* 获取资产数据
* @return
*/
public String getAsset(){
//获取读锁(共享)
this.lock.readLock().lock();
try {
return "账户信息:"+Thread.currentThread().getName()+";账户名称:"+this.name+";总资产:"+asset;
} catch (Exception e) {
return null;
}finally{
//释放读锁
this.lock.readLock().unlock();
}
}
}
public class JUCDemo2 {
public static void main(String[] args) {
Account accout = new Account("QYF", 0.0);
double[] moneys = new double[]{120.0, 100.0, 80.0, 60.0, 40.0, 10.0, 5.0};
//写线程存放资产
for (int i = 0; i < 3; i++) {
new Thread(() -> {
for (int n = 0; n < moneys.length; n++) {
accout.saveMoney(moneys[n]);
}
}).start();
}
//读线程读取数据
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.err.println(accout.getAsset());
}).start();
}
}
}
输出结果:
Thread-1修改银行账户数据:120.0;当前资产:120.0
Thread-1修改银行账户数据:100.0;当前资产:220.0
Thread-1修改银行账户数据:80.0;当前资产:300.0
Thread-1修改银行账户数据:60.0;当前资产:360.0
Thread-1修改银行账户数据:40.0;当前资产:400.0
Thread-1修改银行账户数据:10.0;当前资产:410.0
Thread-1修改银行账户数据:5.0;当前资产:415.0
Thread-0修改银行账户数据:120.0;当前资产:535.0
Thread-0修改银行账户数据:100.0;当前资产:635.0
Thread-0修改银行账户数据:80.0;当前资产:715.0
Thread-0修改银行账户数据:60.0;当前资产:775.0
Thread-0修改银行账户数据:40.0;当前资产:815.0
Thread-0修改银行账户数据:10.0;当前资产:825.0
Thread-0修改银行账户数据:5.0;当前资产:830.0
Thread-2修改银行账户数据:120.0;当前资产:950.0
Thread-2修改银行账户数据:100.0;当前资产:1050.0
Thread-2修改银行账户数据:80.0;当前资产:1130.0
Thread-2修改银行账户数据:60.0;当前资产:1190.0
Thread-2修改银行账户数据:40.0;当前资产:1230.0
Thread-2修改银行账户数据:10.0;当前资产:1240.0
Thread-2修改银行账户数据:5.0;当前资产:1245.0
账户信息:Thread-3;账户名称:QYF;总资产:1245.0
账户信息:Thread-5;账户名称:QYF;总资产:1245.0
账户信息:Thread-4;账户名称:QYF;总资产:1245.0
在程序执行时可以发现写程序采用独占锁的处理方式.多个写线程依次执行.而读线程操作时会有多高线程并行读取.这样既保证了账户数据操作的准确性.也实现了数据的快速读取.