多线程数据脏读实际上我们在前面已经遇到过了,就是前面同一个对象持有一把锁比较类锁,我们先看下脏读的情况:,接下来我们就来聊聊关于java 线程安全变量?以下内容大家不妨参考一二希望能帮到您!

java 线程安全变量(JAVA多线程-数据脏读)

java 线程安全变量

多线程数据脏读实际上我们在前面已经遇到过了,就是前面同一个对象持有一把锁比较类锁,我们先看下脏读的情况:

账户类:

package com.ck.thread; import JAVA.math.BigDecimal; package com.ck.thread; import java.math.BigDecimal; public class account { private String name; private BigDecimal balance = new BigDecimal("0"); public String getName() { return name; } public void setName(String name) { this.name = name; } public BigDecimal getbalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } public synchronized void add(BigDecimal amount) { System.out.println(name ", 开始充值,充值前余额: " balance); try { Thread.sleep(2000); balance = balance.add(amount); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name ", 结束充值,充值后余额: " balance); } public void print() { System.out.println(name ", 当前余额: " balance); } }

我们在写个充值的线程类:

package com.ck.thread; import java.math.BigDecimal; public class CzThread extends Thread{ private Account account; public CzThread(Account account) { this.account = account; } @Override public void run() { account.add(new BigDecimal("100")); } public Account getAccount() { return account; } public void setAccount(Account account) { this.account = account; } }

查询余额:

package com.ck.thread; public class PrintThread extends Thread{ private Account account; public PrintThread(Account account) { this.account = account; } @Override public void run() { account.print(); } public Account getAccount() { return account; } public void setAccount(Account account) { this.account = account; } }

用户先充值再查询余额:

package com.ck.thread; import java.math.BigDecimal; public class MainThread { public static void main(String[] args) throws InterruptedException { Account account1 = new Account(); account1.setName("张三"); account1.setBalance(new BigDecimal("100")); Thread t1 = new CzThread(account1); t1.start(); Thread.sleep(500); Thread t2 = new PrintThread(account1); t2.start(); } }

看下结果:

张三, 开始充值,充值前余额: 100 张三, 当前余额: 100 张三, 结束充值,充值后余额: 200

这时候就出现了脏数据,因为余额应该是200,我们修改下:

package com.ck.thread; import java.math.BigDecimal; public class Account { private String name; private BigDecimal balance = new BigDecimal("0"); public String getName() { return name; } public void setName(String name) { this.name = name; } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } public synchronized void add(BigDecimal amount) { System.out.println(name ", 开始充值,充值前余额: " balance); try { Thread.sleep(2000); balance = balance.add(amount); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name ", 结束充值,充值后余额: " balance); } /**注意这儿加锁了*/ public synchronized void print() { System.out.println(name ", 当前余额: " balance); } }

我们将获取余额也加锁了,我们看下运行结果:

张三, 开始充值,充值前余额: 100 张三, 结束充值,充值后余额: 200 张三, 当前余额: 200

实际上这就是并发问题,我们需要通过锁来实现线程安全问题。

,