java多线程——线程同步问题

本文探讨了Java中多线程环境下线程同步的重要性,通过一个银行账户取款的例子展示了线程安全问题。文章介绍了三种同步解决方案:同步代码块、同步方法和同步锁(Lock)。同步代码块和同步方法使用synchronized关键字,通过锁定对象确保并发访问的安全。同步锁提供了更灵活的控制,包括显示加锁和释放。文章强调了避免死锁和合理选择同步范围的注意事项。
摘要由CSDN通过智能技术生成

试想一个场景:同一个银行账户有1000RMB,两个对象同时对该账户取钱,两人各取800,流程如下:

  1. 输入帐号、密码,验证成功

  2. 输入取钱金额,系统比较账户余额和取钱金额

  3. 验证成功,允许取钱操作,然后,两个人一起开开心心的拿着1.6k回家了。剩下一个余额为-600的账户默默哭泣。

这就是我们常说的:多线程并发操作线程安全问题。

就取钱例子模拟代码实现:

1、定义一个账户类,封装了账户ID和余额两个属性

2、提供取钱线程,执行根据账户信息、取钱数量进行取钱操作

public class Account

    {

        private String accountNo;

        private String balance;

        //省略两个属性的get set方法

 

        //构造器

        public Account(String accountNo,Stringbalance)

        {

            this.accountNo = accountNo;

            this.balance = balance;

        }

        public int hashCode()

        {

            return accountNo.hashCode();

        }

        public boolean equals(Object obj)

        {

            if (obj != null&&obj.getClass()==Account.class)

            { 

                Account target=(Account)obj;

                returntarget.getAccountNo().equals(accountNo);

            }

        return false;

        } 

    }

 

    public class DrawThread extends Thread

    {

        //模拟用户帐户

        private Account account;

        private double drawAmount;

        public DrawThread(String name,Accountaccount,double drawAmount)

        {

            super(name);

            this.account=account;

            this.drawAmount=drawAmount;

        }

 

        //当多条线程同时修改一个共享数据时,将涉及数据安全问题

        public void run()

        {

            //帐户余额>取钱数目

            if(account.getBalance()>=drawAmount)

            {

                //取钞成功

               System.out.println(getName()+"取钱成功,取钱金额为"+drawAmount);

 

                try{

                    Thread.sleep(1);

                }catch(InterruptedException ex)

                {

                    ex.printStackTrace();   

                 }

                 //修改账户余额

               account.setBalance(account.getBalance()-drawAmount);

                System.out.println("余额为"+account.getBalance());

            }

            else

            {

                 System.out.println(getName()+"余额不足");

            }

        }

    }

    

    public class TestDraw

    {

        public static void main(String[] args)

        {

            //创建一个账户

            Account account=newAccount("123",1000);

            //模拟两个线程同时对一个账户取钱

            newDrawThread("Max",account,800).start();

            newDrawThread("Jason",account,800).start();

        }

    }
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值