重温java知识(三十九、JUC并发编程之五:线程锁之ReentrantReadWriteLock)

使用独占锁最大的特点在与其只允许一个线程进行操作,这样进行数据更新的时候可以保证操作的完整性,但是在进行数据读取时,独占锁就会造成严重的性能问题。为了解决高并发下快速访问与安全修改,JUC提供了ReentrantReadWriteLock读/写锁,即在读取的时候上读锁,在写入的时候上写锁,这两种锁是互斥的,有JVM进行控制。
在ReentrantReadWriteLock中读锁属于共享锁,而写锁只允许一个线程进行操作,所以在使用时就需要通过不同的方式获取锁。

1、使用读/写锁实现银行账户的并发写入与并发读取的例子:

package com.mydemo;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class JUCDemo {

    public static void main(String[] args) {

        // 实例化账户
        Account account = new Account("张三", 0.0);

        double moneyData[] = new double[]{100.00, 500.00, 800.00, 5000.00, 10000.00};

        // 5个写入线程
        for(int i = 0; i < 5; i++){
            new Thread(
                    ()->{
                        for(int j = 0; j < moneyData.length; j++){
                            // 存放金额
                            account.saveMoney(moneyData[j]);
                        }
                    }, "写入线程:"
            ).start();
        }

        // 5个读取线程
        for(int i = 0; i < 5; i++){
            new Thread(
                    ()->{
//                        while (true){
//                            // 获取数据
//                            System.err.println(account.toString());
//                        }
                        for(int j = 0; j < 15; j++){
                            System.err.println(account.toString());
                        }
                    }, "读取线程:"
            ).start();
        }
    }
}

// 银行账户
class Account{
    private String name;        // 账户名称
    private double asset;       // 账户资产

    // 读/写锁
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    /**
     * 双参构造函数---设置账户信息
     * @param name
     * @param asset
     */
    public Account(String name, double asset) {
        this.name = name;
        this.asset = asset;
    }

    /**
     * 资产追加
     * @param money
     */
    public void saveMoney(double money){
        // 获取写锁(独占锁)
        this.readWriteLock.writeLock().lock();

        try {
            this.asset += money;    // 资产修改
            TimeUnit.SECONDS.sleep(2); // 模拟延迟
            System.out.println("【" + Thread.currentThread().getName() +
                    "】修改银行资产数据,修改金额:“" + money +
                    "”,当前资产:" + this.asset);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 释放写锁
            this.readWriteLock.writeLock().unlock();
        }
    }

    public String toString() {
        try {
            // 数据读取
            this.readWriteLock.readLock().lock();
            TimeUnit.SECONDS.sleep(1);      // 模拟延迟

            return "【账户信息:("+ Thread.currentThread().getName() +
                    ")】账户名称:" + this.name +
                    "、银行资产" + this.asset;
        } catch (Exception e) {
//            e.printStackTrace();
            return null;
        }finally {
            // 释放读锁
            this.readWriteLock.readLock().unlock();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值