多线程之ReentrantReadWriteLock读/写锁实现并发写入和读取

本文介绍了Java并发编程中使用ReentrantReadWriteLock读写锁来解决高并发下数据读取和修改的安全性与性能问题。通过示例展示了读写锁如何在多线程环境下保证账户数据的正确性和快速读取,从而实现并发控制。
摘要由CSDN通过智能技术生成

使用独占锁最大的特点在于其只允许一个线程进行操作,这样在数据更新的时候可以保证操作的完整性.但是在进行数据读取时,独占锁会造成严重的性能问题,为了解决高并发下的快速访问与安全修改,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

在程序执行时可以发现写程序采用独占锁的处理方式.多个写线程依次执行.而读线程操作时会有多高线程并行读取.这样既保证了账户数据操作的准确性.也实现了数据的快速读取.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值