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

线程同步

在多线程的编程环境下,可能看着没有问题的代码在运行几千上万或者更多次后,出现了一些看着很奇怪的问题,出现这样的问题的原因就是可能会有两个或者更多个线程进入了同一块业务处理代码中导致了判断失效。为了解决这个问题,JAVA引入了同步监视器来解决这个问题。同步监视器的通用方法就是同步代码块,也就是给一块代码加了同步锁。

package cn.test.hf;

import java.math.BigDecimal;

/**

* 模拟取钱操作

*/

public class RunnableTest implements Runnable {

private Account account;

// 当前用户想取的钱

private BigDecimal withdrawal;

public RunnableTest(Account account, BigDecimal withdrawal) {

this.account = account;

this.withdrawal = withdrawal;

}

public void run() {

// 判断当前用户取钱的数目是否超出余额

if (this.withdrawal.subtract(this.account.getHaveMoney()).doubleValue() <= 0) {

// 取钱之后将账户的余额减少

this.account.setHaveMoney(this.account.getHaveMoney().subtract(this.withdrawal));

System.out.println("当前用户" + Thread.currentThread().getName() + "取出金额" + this.withdrawal + ",取款成功!");

} else {

System.out.println("当前用户" + Thread.currentThread().getName() + "取的金额" + this.withdrawal + "超出限制!");

}

}

public static void main(String[] args) {

try {

Account account = new Account();

account.setHaveMoney(new BigDecimal(1000));

account.setRemainMoney(new BigDecimal(1000));

RunnableTest r1 = new RunnableTest(account, new BigDecimal("800"));

RunnableTest r2 = new RunnableTest(account, new BigDecimal("900"));

Thread t1 = new Thread(r1, "张三");

t1.start();

Thread t2 = new Thread(r2, "李四");

t2.start();

// 完成之后再还原

} catch (Exception e) {

}

}

}

eed11c22523a8ca34dab8fc102f73ec9.png

在高并发的情况下,张三和李四操作了同一个账户,可能会出现的问题是张三和李四取钱都成功了,那么账户的余额就为负数了。

处理这种问题

方法1、使用synchronized(obj)同步代码块来锁定当前的obj对象,obj就是同步监视器,任何时刻只有一个线程可以获得对同步监视器的锁定,线程操作完后释放对象锁。

代码如下:

public void run() {

synchronized (this.account) {

// 判断当前用户取钱的数目是否超出余额

if (this.withdrawal.subtract(this.account.getHaveMoney()).doubleValue() <= 0) {

// 取钱之后将账户的余额减少

this.account.setHaveMoney(this.account.getHaveMoney().subtract(this.withdrawal));

System.out.println("当前用户" + Thread.currentThread().getName() + "取出金额" + this.withdrawal + ",取款成功!");

} else {

System.out.println("当前用户" + Thread.currentThread().getName() + "取的金额" + this.withdrawal + "超出限制!");

}

}

}

方法二、使用同步方法,同步方法和同步代码块对应,同步方法就是使用synchronized来修饰某个方法,对于synchronized修改的实例方法无须显示指定同步控制器,同步方法的同步监视器就是当前对象,也就是this,不可变类总是线程安全的,可变类不是线程安全的,所以可以通过synchronized来修饰对应的set方法来控制多线程并发访问。

1、同步锁

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值