zoukankan      html  css  js  c++  java
  • 高并发锁的问题

    场景分析,

    1. 保护多个资源之间没有业务关系

        例如支付宝账户的针对余额的操作,和针对账户密码的修改操作。可以为账户资源,用户资源分配不同的锁来解决并发问题。

        

    public class AlipayAccount{
        //保护balance资源的锁对象
        private final Object balanceLock = new Object();
        //保护password资源的锁对象
        private final Object passwordLock = new Object();
        //账户余额
        private Integer balance;
        //账户的密码
        private String password;
        
        //支付方法
        public void pay(Integer money){
            synchronized(balanceLock){
                if(this.balance >= money){
                    this.balance -= money;
                }
            }
        }
        //查看账户中的余额
        public Integer getBalance(){
            synchronized(balanceLock){
                return this.balance;
            }
        }
        
        //修改账户的密码
        public void updatePassword(String password){
            synchronized(passwordLock){
                this.password = password;
            }
        }
        
        //查看账户的密码
        public String getPassword(){
            synchronized(passwordLock){
                return this.password;
            }
        }
    }
    

      这里也可以用一吧锁来保护balance和password 资源,甚至干脆用this关键字和synchronized关键字操作。但是,如果使用一个锁对象的话,那么程序的性能太差了,会导致直接业务各种操作都串行执行,这违背了程序并发遍程的目的

    1. 多个资源之间有业务关系

      例如,我们使用支付宝进行转账操作。假设账户A给账户B转账100,A账户减少100元,B账户增加100元。两个账户在业务中有直接的业务关系。例如,下面的TansferAccount类,有一个成员变量balance和一个转账的方法transfer(),代码如下所示。

    public class TansferAccount{
        private Integer balance;
        public void transfer(TansferAccount target, Integer transferMoney){
            if(this.balance >= transferMoney){
                this.balance -= transferMoney;
                target.balance += transferMoney;
            }
        }
    }
    

      在上面的代码中,如何保证转账操作不会出现并发问题呢?很多时候我们的第一反应就是给transfer()方法加锁,如下代码所示

    public class TansferAccount{
        private Integer balance;
        public synchronized void transfer(TansferAccount target, Integer transferMoney){
            if(this.balance >= transferMoney){
                this.balance -= transferMoney;
                target.balance += transferMoney;
            }
        }
    }
    

      

    我们仔细分析下,上面的代码真的是安全的吗?!其实,在这段代码中,synchronized临界区中存在两个不同的资源,分别是转出账户的余额this.balance和转入账户的余额target.balance,这里只用到了一把锁synchronized(this)。说到这里,大家有没有一种豁然开朗的感觉。没错,问题就出现在synchronized(this)这把锁上,这把锁只能保护this.balance资源,而无法保护target.balance资源。

    解决方法:

    1:统一给他们传入一个锁资源。在实际的开发中,不同实例在不同的模块中,该方法不显示

    2.:统一使用类锁。对他们进行处理。

  • 相关阅读:
    DevExpress RichEditControl 上下翻页功能 z
    DockManager 如何快速隐藏DockPanel z
    DevExpress SpreadSheet报表模板设置 z
    DocumentManager在标签位置显示气泡框 z
    C#,数据类型扩展 z
    [安卓] 6、列表之ArrayAdapter适配
    [安卓] 5、SeekBar拖动条
    [安卓] 4、CheckBox、RadioButton和Toast简单用法
    [安卓] 3、EditText使用小程序
    [安卓] 2、使用2中方法做按钮监听和图片按钮使用
  • 原文地址:https://www.cnblogs.com/dousil/p/12689527.html
Copyright © 2011-2022 走看看