线程安全
- 同步:队列+锁
- 性能问题
- 每个线程都有自己的工作内存
测试1、买票
public class TicketTest { public static void main(String[] args) { Ticket ticket = new Ticket(); new Thread(ticket,"小明").start(); new Thread(ticket,"Jay").start(); new Thread(ticket,"黄牛").start(); } } class Ticket implements Runnable{ int num = 10; @Override public void run() { synchronized (Ticket.class){ while (true){ try { Thread.sleep(1000); } catch (InterruptedException e) { } if(num <= 0) break;; System.out.println(Thread.currentThread().getName()+"取到票"+num--); } } } }
测试2、取钱
/** * 账户余额100,老公妻子各自支取70,余额不足,发生冲突 */ public class BankAccountTest { public static void main(String[] args) { BankAccount account = new BankAccount(100, "【生活费】"); BankAccountTest bankAccountTest = new BankAccountTest(); new Thread(new Withdraw(account, 30), "wife").start(); new Thread(new Withdraw(account, 90), "husband").start(); } } /** * 银行取钱 */ class Withdraw implements Runnable { BankAccount account; int drawingMoney; public Withdraw(BankAccount account, int drawingMoney) { this.account = account; this.drawingMoney = drawingMoney; } @Override public void run() { synchronized (account) { if (drawingMoney - account.getBalance() > 0) { System.out.println(Thread.currentThread().getName() + "卡内余额不足"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { } account.setBalance(account.getBalance() - drawingMoney); System.out.println(Thread.currentThread().getName() + "取了" + drawingMoney); System.out.println(account.getId() + "余额为" + account.getBalance()); } } } /** * 银行账号 */ class BankAccount { private int balance;//余额 private String id;//卡号 public BankAccount(int balance, String id) { this.balance = balance; this.id = id; } public int getBalance() { return balance; } public BankAccount setBalance(int balance) { this.balance = balance; return this; } public String getId() { return id; } public BankAccount setId(String id) { this.id = id; return this; } }
测试3、集合的使用
public class JUCTest { public static void main(String[] args) { //List<String> list = new CopyOnWriteArrayList<String>(); List<String> list = new ArrayList<String>(); //添加10000个线程到该集合 for (int i = 0; i < 10000; i++) { new Thread(() -> { synchronized (list){ list.add(Thread.currentThread().getName()); } }).start(); } //延长时间让线程执行完毕 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
测试4、死锁
相互等待对方的资源,形成僵持
- 互斥条件:一个资源每次只能被一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对方已获得的资源保持不放。
- 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种首尾相接的循环等待资源关系。
public class DeadLockTest { public static void main(String[] args) { Object lock1 = new Object(); Object lock2 = new Object(); new Thread(new DeadLock(lock1,lock2,1)).start(); new Thread(new DeadLock(lock1,lock2,2)).start(); } } class DeadLock implements Runnable{ private int choice; private Object lock1; private Object lock2; public DeadLock( Object lock1, Object lock2, int choice){ this.choice = choice; this.lock1 = lock1; this.lock2 = lock2; } @Override public void run() { try { if(choice == 1){ synchronized (lock1){ System.out.println(Thread.currentThread().getName()+"获得lock1锁"); Thread.sleep(1000); synchronized (lock2){ System.out.println(Thread.currentThread().getName()+"获得lock2锁"); } } } else { synchronized (lock2){ System.out.println(Thread.currentThread().getName()+"获得lock2锁"); Thread.sleep(2000); synchronized (lock1){ System.out.println(Thread.currentThread().getName()+"获得lock1锁"); } } } } catch (InterruptedException e) { } } }