一、线程同步
不安全的案例:
//不安全买票 public class Demo24_UnsafeBuyTicket { public static void main(String[] args) { BuyTicket buyTicket = new BuyTicket(); new Thread(buyTicket, "张三").start(); new Thread(buyTicket, "李四").start(); new Thread(buyTicket, "王五").start(); } } class BuyTicket implements Runnable { //票 private int ticketNums = 10; boolean flag = true; @Override public void run() { //买票 while (flag) { try { buy(); } catch (Exception e) { e.printStackTrace(); } } } //买票 private void buy() { //判断是否有票 if (ticketNums <= 0) { flag = false; return; } //延迟 try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //买票 System.out.println(Thread.currentThread().getName() + "拿到" + ticketNums--); } }
/** * 不安全的取钱 */ public class Demo25_UnsafeBank { public static void main(String[] args) { Account account = new Account(100, "结婚基金"); Drawing you = new Drawing(account, 50, "展堂"); Drawing girlfriend = new Drawing(account, 100, "sad"); you.start(); girlfriend.start(); } } //账户 class Account { int money;//余额 String cardName;//卡名 public Account(int money, String cardName) { this.money = money; this.cardName = cardName; } } //银行:模拟取款 class Drawing extends Thread { Account account;//账户 int drawingMoney;//取金额 int nowMoney;//你手里的钱 public Drawing(Account account, int drawingMoney, String name) { super(name); this.account = account; this.drawingMoney = drawingMoney; } //取钱 @Override public void run() { //判断是否有钱 if (account.money - drawingMoney < 0) { System.out.println(Thread.currentThread().getName() + "余额不足,不能进行取钱"); return; } try { Thread.sleep(1000);//放大问题的发生性 } catch (InterruptedException e) { e.printStackTrace(); } //卡内金额 = 余额-你的钱 account.money = account.money - drawingMoney; //你手里的钱 nowMoney = nowMoney + drawingMoney; System.out.println(account.cardName + "余额为:" + account.money); //this.getName()==Thread.currentThread().getName() System.out.println(this.getName() + "手里的钱:" + nowMoney); } }
//线程不安全的集合 public class Demo26_UnsafeList { public static void main(String[] args) { List<String> list = new ArrayList<String>(); for (int i = 0; i < 1000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } System.out.println(list.size()); } }
同步方法,锁的是this
//安全买票 public class Demo27_SafeBuyTicket { public static void main(String[] args) { BuyTicket1 buyTicket = new BuyTicket1(); new Thread(buyTicket, "张三").start(); new Thread(buyTicket, "李四").start(); new Thread(buyTicket, "王五").start(); } } class BuyTicket1 implements Runnable { //票 private int ticketNums = 10; boolean flag = true; @Override public void run() { //买票 while (flag) { try { buy(); } catch (Exception e) { e.printStackTrace(); } } } //synchronized 同步方法,锁的是this private synchronized void buy() { //判断是否有票 if (ticketNums <= 0) { flag = false; return; } //延迟 try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //买票 System.out.println(Thread.currentThread().getName() + "拿到" + ticketNums--); } }
/** * 安全的取钱 同步块 */ public class Demo28_SafeBank { public static void main(String[] args) { Account1 account = new Account1(100, "结婚基金"); Drawing1 you = new Drawing1(account, 50, "展堂"); Drawing1 girlfriend = new Drawing1(account, 100, "sad"); you.start(); girlfriend.start(); } } //账户 class Account1 { int money;//余额 String cardName;//卡名 public Account1(int money, String cardName) { this.money = money; this.cardName = cardName; } } //银行:模拟取款 class Drawing1 extends Thread { Account1 account;//账户 int drawingMoney;//取金额 int nowMoney;//你手里的钱 public Drawing1(Account1 account, int drawingMoney, String name) { super(name); this.account = account; this.drawingMoney = drawingMoney; } //取钱 @Override public void run() { //锁的对象就是变量的量,需要增删改查的对象 synchronized (account) { //判断是否有钱 if (account.money - drawingMoney < 0) { System.out.println(Thread.currentThread().getName() + "余额不足,不能进行取钱"); return; } try { Thread.sleep(1000);//放大问题的发生性 } catch (InterruptedException e) { e.printStackTrace(); } //卡内金额 = 余额-你的钱 account.money = account.money - drawingMoney; //你手里的钱 nowMoney = nowMoney + drawingMoney; System.out.println(account.cardName + "余额为:" + account.money); //this.getName()==Thread.currentThread().getName() System.out.println(this.getName() + "手里的钱:" + nowMoney); } }
//线程安全的集合 同步块 public class Demo29_SafeList { public static void main(String[] args) { List<String> list = new ArrayList<String>(); for (int i = 0; i < 1000; i++) { new Thread(() -> { synchronized (list) { list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
/** * 死锁:多个线程互相抱着对方需要的资源,然后形成僵持 * 解决:一个锁只锁一个对象 */ class Demo31_DeadLock { public static void main(String[] args) { Makeup makeup = new Makeup(0, "灰姑娘"); Makeup makeup1 = new Makeup(1, "白雪公主"); makeup.start(); makeup1.start(); } } //口红 class Lipstick { } //镜子 class Mirror { } class Makeup extends Thread { //需要的资源只有一份,用static保证只有一份 static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror(); int choice;//选择 String girlName;//使用化妆品的人 public Makeup(int choice, String girlName) { this.choice = choice; this.girlName = girlName; } @Override public void run() { //化妆 try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } } private void makeup() throws InterruptedException { if (choice == 0) { synchronized (lipstick) {//获得口红的锁 System.out.println(this.girlName + "获得口红的锁"); Thread.sleep(1000); synchronized (mirror) {//一秒钟后想获得镜子 System.out.println(this.girlName + "获得镜子的锁"); } } } else { synchronized (mirror) {//获得口红镜子 System.out.println(this.girlName + "获得镜子的锁"); Thread.sleep(2000); synchronized (lipstick) {//二秒钟后想获得的锁 System.out.println(this.girlName + "获得口红的锁"); } } } } }
//测试Lock锁 public class Demo32_ThreadLock { public static void main(String[] args) { TestLock testLock = new TestLock(); new Thread(testLock).start(); new Thread(testLock).start(); new Thread(testLock).start(); } } class TestLock implements Runnable { int tickerNums = 10; //定义Lock锁 private final ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true) { //加锁 try { lock.lock(); if (tickerNums <= 0) { break; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(tickerNums--); } catch (Exception e) { e.printStackTrace(); } finally { //解锁 lock.unlock(); } } } }