模拟抢票
package TCPUDPThread; /** * 抢票 * * 线程同步 * 并发控制:synchronized * * 准确性:线程安全 * * 线程不安全:数据有负数/相同 * * 队列与锁 * 并发:同一个对象多个线程同时操作 * * 线程同步 * 由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了 * 访问冲突的问题.为了保证数据在方法中被访问时的正确性,在访问时加入 * 锁机制(synchronized),当一个线程获得对象的排它锁,独占资源,其他线程 * 必须等待,使用后释放锁即可.存在以下问题: * 一个线程持有锁会导致其他所有需要此锁的线程挂起; * 在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题; * 如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能问题. * * 由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们 * 只需针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法: * synchronized方法和synchronized块. * * 同步方法 * publci synchronized void method(int args){} * * synchronized方法控制对"成员变量|类变量"对象的访问:每个对象对应一把锁,每个 * synchronized方法都必须获得调用该方法的对象的锁方能执行,否则所属线程阻塞,方法 * 一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁, * 重新进入可执行状态。 * * 缺陷:若将一个大的方法声明为synchronized将会大大影响效率. * * 锁对象,操作成员方法锁this,静态方法锁class对象 * * 线程同步的难点:①数据安全准确 ②性能 * * ①目标要对 * ②效率要高 * * 线程安全:在并发时保证数据的正确性,效率尽可能高 * synchronized * 1.同步方法 * 2.同步块 * @author pmc * */ public class synchronizedTest4 { public static void main(String[] args){ Webss12306 we=new Webss12306(); new Thread(we,"*1*").start(); new Thread(we,"*2*").start(); new Thread(we,"*3*").start(); } } class Webss12306 implements Runnable { //票数 private int p=10; private boolean flag=true; @Override public void run() { while(flag){ test(); } } private synchronized void test(){ if(p<=0){ flag=false; return; } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->"+p--); } }模拟取钱
package TCPUDPThread; /** * 取钱 * * @author pmc * */ public class synchronizedTest2 { public static void main(String[] args) { //银行账户 Account ac=new Account(1000,"老王"); Drawing dr=new Drawing(ac,50,"小王"); Drawing drs=new Drawing(ac,580,"小张"); dr.start(); drs.start(); } } // 模拟银行 class Account { final String CN="123456789"; long money;// 钱 String name;// 名 public Account(long money, String name) { this.money = money; this.name = name; System.out.println("银行账户:"+CN); System.out.println("账户余额:"+money+"万美金"); } } // 模拟取款 class Drawing extends Thread { Account account;// 取钱账户 int drMoney;// 取钱数 int drTotal;// 取的总数 @Override public void run() { test(); } //目标锁定account public void test(){ if(account.money<=0){ return; } //锁账户 synchronized(account){ if(account.money - drMoney<0){ return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } account.money -= drMoney; drTotal += drMoney; } System.out.println(this.getName() + "-->账户余额" + account.money); System.out.println(this.getName() + "-->到账金额" + drTotal); } public Drawing(Account cccount, int drMoney, String name) { super(name);// 线程名 this.account = cccount; this.drMoney = drMoney; } }模拟容器
package TCPUDPThread; import java.util.ArrayList; import java.util.List; /** * 操作容器 * * @author pmc * */ public class synchronizedTest3 { public static void main(String[] args) throws Exception { List<String> list = new ArrayList<String>(); for(int i=0;i<10000;i++){ new Thread(()->{ //并发同步 synchronized(list){ list.add(Thread.currentThread().getName()); } }).start(); } //执行过快,手动加延时 Thread.sleep(2000); System.out.println(list.size()); } }