多线程同步机制2-深入理解synchronized关键字
2017-09-09 01:31
393 查看
上一节讲了关键字synchronized的基本用法。这一节我将用一个实际的例子来深入多线程同步机制的理解。
首先上面代码:
1.账户初始化余额1000
2.Bank有两个方法,分别是取钱和存钱的操作,取钱和存钱的操作分别传入了金额和渠道(ATM 柜台),都使用了synchronized关键字。
3.四个多线程。ATM取钱、ATM存钱、柜台存钱、柜台取钱,对其存钱和取钱的操作。
4.增加一个查询余额searchBalance()的方法,查询余额,没有关键字synchronized.
5. 模拟存钱需要等待10S,即 Thread.sleep(10000);
6.main方法中,我们多次调用查询余额方法,然后启动多个线程去操作同一个账户。分别通过ATM和柜台去存800和取款800。
如果余额依然是1000,那么说明多线程同步机制起到了实质的作用。
上面代码可以直接copy到本地执行
存取款改造
/** * Created by qianyi on 2017/9/9. */ public class FetchOperationMoney { public static void main(String[] args) { Bank bank = new Bank(); Thread t1 = new AtmSaveMoney(bank);//ATM存钱 Thread t2 = new GuitaiSaveMoney(bank);//柜台存钱 Thread t3 = new AtmFetchMoney(bank);//ATM取钱 Thread t4 = new GuiTaiFetchMoney(bank);//柜台取钱 //分别启动四个线程去对账户进行操作 bank.searchBalance();//访问没有加synchronized的方法, t1.start(); bank.searchBalance();//访问没有加synchronized的方法, t2.start(); bank.searchBalance();//访问没有加synchronized的方法, t3.start(); bank.searchBalance();//访问没有加synchronized的方法, t4.start(); bank.searchBalance();//访问没有加synchronized的方法, } } /** * 银行账户 */ class Bank { /** * 账户余额 */ private int balance = 1000; /** * 操作取钱的方法 * * @param number 取钱金额 * @return */ public synchronized int fetchMoney(int number, String channel) { System.out.println("取款开始:"); System.out.println("取款来自渠道:" + channel + ",账户操作前余额:" + balance); System.out.println("账户取款金额:" + number); if (number < 0) { return -1; } else if (number > balance) { return -2; } else if (balance < 0) { return -3; } else { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } balance -= number; System.out.println("balance is:" + balance); System.out.println("------------------------------------------------"); return number; } } /** * 存钱 * * @param number 存钱金额 * @return */ public synchronized int saveMoney(int number, String channel) { System.out.println("存款开始:"); System.out.println("存款款来自渠道:" + channel + ",账户操作前余额:" + balance); System.out.println("账户存款金额:" + number); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } balance += number; System.out.println("balance is:" + balance); System.out.println("------------------------------------------------"); return number; } /** * 查询余额,没有关键字synchronized */ public void searchBalance() { System.out.println("*****************************************"); System.out.println("查询----账户余额为:" + balance); System.out.println("*****************************************"); } } /** * ATM取钱 */ class AtmFetchMoney extends Thread { private Bank bank; public AtmFetchMoney(Bank bank) { this.bank = bank; } @Override public void run() { bank.fetchMoney(800, "ATM"); } } /** * 柜台取钱 */ class GuiTaiFetchMoney extends Thread { private Bank bank; public GuiTaiFetchMoney(Bank bank) { this.bank = bank; } @Override public void run() { bank.fetchMoney(800, "柜台"); } } /** * 柜台存钱 */ class GuitaiSaveMoney extends Thread { private Bank bank; public GuitaiSaveMoney(Bank bank) { this.bank = bank; } @Override public void run() { bank.saveMoney(800, "柜台"); } } /** * ATM存钱 */ class AtmSaveMoney extends Thread { private Bank bank; public AtmSaveMoney(Bank bank) { this.bank = bank; } @Override public void run() { bank.saveMoney(800, "ATM"); } }
首先上面代码:
1.账户初始化余额1000
2.Bank有两个方法,分别是取钱和存钱的操作,取钱和存钱的操作分别传入了金额和渠道(ATM 柜台),都使用了synchronized关键字。
3.四个多线程。ATM取钱、ATM存钱、柜台存钱、柜台取钱,对其存钱和取钱的操作。
4.增加一个查询余额searchBalance()的方法,查询余额,没有关键字synchronized.
5. 模拟存钱需要等待10S,即 Thread.sleep(10000);
6.main方法中,我们多次调用查询余额方法,然后启动多个线程去操作同一个账户。分别通过ATM和柜台去存800和取款800。
如果余额依然是1000,那么说明多线程同步机制起到了实质的作用。
结果:
***************************************** 查询----账户余额为:1000 ***************************************** ***************************************** 查询----账户余额为:1000 ***************************************** 存款开始: ***************************************** 查询----账户余额为:1000 ***************************************** 存款款来自渠道:ATM,账户操作前余额:1000 账户存款金额:800 ***************************************** 查询----账户余额为:1000 ***************************************** ***************************************** 查询----账户余额为:1000 ***************************************** balance is:1800 ------------------------------------------------ 取款开始: 取款来自渠道:柜台,账户操作前余额:1800 账户取款金额:800 balance is:1000 ------------------------------------------------ 取款开始: 取款来自渠道:ATM,账户操作前余额:1000 账户取款金额:800 balance is:200 ------------------------------------------------ 存款开始: 存款款来自渠道:柜台,账户操作前余额:200 账户存款金额:800 balance is:1000 ------------------------------------------------
总结如下:
通过上面的例子可以发现,没有加synchronized关键字的方法searchBalance()不受同步机制的影响。其余的方法存款取款依次操作。不会出现竞争统一资源导致数据不对。只有当第一个线程将对象锁释放之后,后面才有执行。上面代码可以直接copy到本地执行
相关文章推荐
- 深入理解synchronized关键字
- Java线程同步机制synchronized关键字的理解
- 深入理解java中的synchronized关键字
- Java线程同步机制synchronized关键字的理解
- Java线程同步机制synchronized关键字的理解
- 深入理解java中的synchronized关键字
- 深入理解java中的synchronized关键字
- 深入理解Java并发机制(2)--volatile关键字
- 深入理解java中的synchronized关键字
- 深入理解Java并发机制(2)--volatile关键字
- 深入理解Java并发4——synchronized关键字
- 深入理解Java并发机制(2)--volatile关键字
- 深入理解java中的synchronized关键字
- 深入理解Java并发机制(2)--volatile关键字
- 深入理解Java并发机制(2)--volatile关键字
- 深入理解java中的synchronized关键字
- Java同步关键字Synchronized深入理解
- 深入理解Java并发机制(2)--volatile关键字
- 深入理解java中的synchronized关键字
- Java线程同步机制synchronized关键字的理解