并发实际场景(保持余额操作的正确)
场景:
一个人在一家银行办了一个账户,银行给了 一张卡(存取款)、一本存折(存取款)、一个网银(查询余额)
卡和存储不断存款和取款,网银不断查询余额。如何保持余额的正确。
例子(线程不安全):
控制器代码:
@Controller
public class TestController {// 开个银行帐号Acount3 account = new Acount3();@RequestMapping(value="/cardAddAcount")@ResponseBodypublic TaotaoResult cardAddAcount(){TaotaoResult result = new TaotaoResult();result.setData("+100, 余额: " + account.addAcount("card", 100));return result;}@RequestMapping(value="/passbookAddAcount")@ResponseBodypublic TaotaoResult passbookAddAcount(){TaotaoResult result = new TaotaoResult();result.setData("+100, 余额: " + account.addAcount("存折", 100));return result;}@RequestMapping(value="/cardSubAcount")@ResponseBodypublic TaotaoResult cardSubAcount(){TaotaoResult result = new TaotaoResult();result.setData("-150, 余额: " + account.subAcount("card", 150));return result;}@RequestMapping(value="/passbookSubAcount")@ResponseBodypublic TaotaoResult passbookSubAcount(){TaotaoResult result = new TaotaoResult();result.setData("-200, 余额: " + account.subAcount("存折", 200));return result;}@RequestMapping(value="/selectAcount")@ResponseBodypublic TaotaoResult selectAcount(){TaotaoResult result = new TaotaoResult();result.setData(account.selectAcount(""));return result;}
}
账户3(线程不安全):
/*** 银行账户:无任何并发处理** @author Administrator*/
public class Acount3 {private int count = 0;/*** 存钱** @param money*/public int addAcount(String name, int money) {// 存钱count += money;System.out.println(name + "...存入:" + money + "..." + Thread.currentThread().getName());return selectAcount(name);}/*** 取钱** @param money*/public int subAcount(String name, int money) {// 先判断账户现在的余额是否够取钱金额if (count - money < 0) {System.out.println("账户余额不足!余额=" + count);return money;}// 取钱count -= money;System.out.println(name + "...取出:" + money + "..." + Thread.currentThread().getName());return selectAcount(name);}/*** 查询余额*/public int selectAcount(String name) {System.out.println(name + "...余额:" + count);return count;}
}
账户3(线程不安全)执行的结果:

例子2:
账户2(线程安全):给每个方法加上synchronized 实现
/*** 银行账户:线程安全** @author Administrator*/
public class Acount2 {private int count = 0;/*** 存钱** @param money*/public synchronized int addAcount(String name, int money) {// 存钱count += money;System.out.println(name + "...存入:" + money + "..." + Thread.currentThread().getName());return selectAcount(name);}/*** 取钱** @param money*/public synchronized int subAcount(String name, int money) {// 先判断账户现在的余额是否够取钱金额if (count - money < 0) {System.out.println("账户余额不足!余额=" + count);return money;}// 取钱count -= money;System.out.println(name + "...取出:" + money + "..." + Thread.currentThread().getName());return selectAcount(name);}/*** 查询余额*/public synchronized int selectAcount(String name) {System.out.println(name + "...余额:" + count);return count;}
}
例子1:
账户1(线程安全):通过lock来实现
import java.util.concurrent.locks.ReentrantLock;/*** 银行账户:线程安全** @author Administrator*/
public class Acount {private int count = 0;private ReentrantLock lock = new ReentrantLock();/*** 存钱** @param money*/public int addAcount(String name, int money) {lock.lock();try {// 存钱count += money;System.out.println(name + "...存入:" + money + "..." + Thread.currentThread().getName());} finally {lock.unlock();}return selectAcount(name);}/*** 取钱** @param money*/public int subAcount(String name, int money) {lock.lock();try {// 先判断账户现在的余额是否够取钱金额if (count - money < 0) {System.out.println("账户余额不足!余额=" + count);return money;}// 取钱count -= money;System.out.println(name + "...取出:" + money + "..." + Thread.currentThread().getName());} finally {lock.unlock();}return selectAcount(name);}/*** 查询余额*/public int selectAcount(String name) {lock.lock();try {System.out.println(name + "...余额:" + count);} finally {lock.unlock();}return count;}
}
代码demo:
链接:https://pan.baidu.com/s/1i_uzZKd-GC-8NPa1hFdw8w 密码:rht7
测试用例:

链接:https://pan.baidu.com/s/1Ri54rR1k7JETO6i5pDyVlw 密码:u96e
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
