JUC学习笔记——共享模型之管程( 五 )

/*转账问题*/// 源码展示public class ExerciseTransfer {public static void main(String[] args) throws InterruptedException {Account a = new Account(1000);Account b = new Account(1000);Thread t1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {a.transfer(b, randomAmount());}}, "t1");Thread t2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {b.transfer(a, randomAmount());}}, "t2");t1.start();t2.start();t1.join();t2.join();// 查看转账2000次后的总金额log.debug("total:{}",(a.getMoney() + b.getMoney()));}// Random 为线程安全static Random random = new Random();// 随机 1~100public static int randomAmount() {return random.nextInt(100) +1;}}class Account {private int money;public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}public void transfer(Account target, int amount) {if (this.money > amount) {this.setMoney(this.getMoney() - amount);target.setMoney(target.getMoney() + amount);}}}// 问题分析:我们的transfer方法中存在两个对象,一个自身对象,一个被转账用户对象,所以无法使用synchronized方法但是我们可以暂时将他设置为 static synchronized 直接对账户整体进行上锁来处理问题~// 修改后代码:public class ExerciseTransfer {public static void main(String[] args) throws InterruptedException {Account a = new Account(1000);Account b = new Account(1000);Thread t1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {a.transfer(b, randomAmount());}}, "t1");Thread t2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {b.transfer(a, randomAmount());}}, "t2");t1.start();t2.start();t1.join();t2.join();log.debug("total:{}",(a.getMoney() + b.getMoney()));}static Random random = new Random();public static int randomAmount() {return random.nextInt(100) +1;}}class Account {private int money;public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}public static synchronized void transfer(Account target, int amount) {if (this.money > amount) {this.setMoney(this.getMoney() - amount);target.setMoney(target.getMoney() + amount);}}}Monitor这小节我们将会介绍Monitor
Java对象头在正式开始Monitor介绍之前,我们先来介绍一下Java对象头的定义:
# 以下内容均以32位虚拟机为例# 普通对象|--------------------------------------------------------------||Object Header (64 bits)||------------------------------------|-------------------------||Mark Word (32 bits)|Klass Word (32 bits)||------------------------------------|-------------------------|# 数组对象|---------------------------------------------------------------------------------||Object Header (96 bits)||--------------------------------|-----------------------|------------------------||Mark Word(32bits)|Klass Word(32bits)|array length(32bits)||--------------------------------|-----------------------|------------------------|# 其中 Mark Word 结构为|-------------------------------------------------------|--------------------||Mark Word (32 bits)|State||-------------------------------------------------------|--------------------||hashcode:25| age:4 |biased_lock:0|01|Normal||-------------------------------------------------------|--------------------||thread:23|epoch:2| age:4 |biased_lock:1|01|Biased||-------------------------------------------------------|--------------------||ptr_to_lock_record:30|00| Lightweight Locked ||-------------------------------------------------------|--------------------||ptr_to_heavyweight_monitor:30|10| Heavyweight Locked ||-------------------------------------------------------|--------------------|||11|Marked for GC||-------------------------------------------------------|--------------------|# 其中Klass Word主要存储对象类型名称# 64位虚拟机的 Mark Word 结构为|--------------------------------------------------------------------|--------------------||Mark Word (64 bits)|State||--------------------------------------------------------------------|--------------------|| unused:25 | hashcode:31 | unused:1 | age:4 | biased_lock:0 |01|Normal||--------------------------------------------------------------------|--------------------|| thread:54 |epoch:2| unused:1 | age:4 | biased_lock:1 |01|Biased||--------------------------------------------------------------------|--------------------||ptr_to_lock_record:62|00| Lightweight Locked ||--------------------------------------------------------------------|--------------------||ptr_to_heavyweight_monitor:62|10| Heavyweight Locked ||--------------------------------------------------------------------|--------------------|||11|Marked for GC||--------------------------------------------------------------------|--------------------|Monitor概述我们来简单介绍一下Monitor: