卖票
package org.example.concurrency.test;import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;import java.util.List;import java.util.Vector;/*** @author huskyui*/@Slf4jpublic class ExerciseSell {public static void main(String[] args) {TicketWindow window = new TicketWindow(10000);//List<Integer> amountList = new Vector<>();List<Thread> threadList = new ArrayList<>();for (int i = 0;i<2000;i++){Thread thread = new Thread(()->{try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}int amount = window.sell(1);amountList.add(amount);});threadList.add(thread);thread.start();}threadList.forEach(t-> {try {t.join();} catch (InterruptedException e) {e.printStackTrace();}});log.info("余票:{}",window.getCount());int count = 0;for (int amount : amountList){count+=amount;}log.info(" 余票2 : {}",count);}}class TicketWindow{private int count;public TicketWindow(int count){this.count = count;}public int getCount(){return count;}// public synchronized int sell(int amount){// if(this.count >= amount){// this.count -=amount;// return amount;// }else{// return 0;// }// }public int sell(int amount){synchronized (this) {if (this.count >= amount) {this.count -= amount;return amount;} else {return 0;}}}}
我们可以看到,多个线程对一个对象进行竞争访问的时候,我们加入 关键字 synchronized 就可以锁定 当前创建的 TicketWindow window = new TicketWindow(10000);
转账
package org.example.concurrency.test;import lombok.extern.slf4j.Slf4j;import java.util.Random;/*** @author huskyui*/@Slf4jpublic class ExerciseTransfer {public static void main(String[] args) throws InterruptedException {Account account1 = new Account(1000);Account account2 = new Account(1000);Thread t1 = new Thread(() -> {for (int i = 0; i < 100; i++) {account1.transfer(account2, randomAmount());}}, "t1");Thread t2 = new Thread(() -> {for (int i = 0; i < 100; i++) {account2.transfer(account1, randomAmount());}}, "t2");t1.start();t2.start();t1.join();t2.join();log.info("余额 {}", account1.getMoney() + account2.getMoney());}// random 为线程安全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 void transfer(Account target, int amount) {synchronized (Account.class) {if (this.money >= amount) {this.setMoney(this.getMoney() - amount);target.setMoney(target.getMoney() + amount);}}}}
我们可以转账时,我们需要同时给两个account对象加锁,我们如果还是想之前的方式,进行加锁就会出现问题
public synchronized void transfer(Account target, int amount) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}if (this.money >= amount) {this.setMoney(this.getMoney() - amount);System.out.println(target.getMoney());target.setMoney(target.getMoney() + amount);}}
所以我们可以锁住Account.class这个类。但是这个效率低。
