package com.atguigu.test09; /* * 举例:卖票 * 假设,有10张票,分三个窗口同时卖 * * 1、线程安全问题: * 当多个线程使用“共享数据”时,就会有线程安全问题。 * 当一个线程修改了“共享数据”,是会影响其他线程。 * * 2、如何解决? * 加锁 * * 形式一:同步代码块 * 形式二:同步方法 * * 3、同步代码块 * 语法格式: * synchronized(锁对象){ * 需要加锁的代码 * } * * 锁对象,又称为监视器对象,同一时刻,某一段代码,只允许一个线程运行,这个锁就记录谁现在在运行,其他线程进不来。 * * 锁对象的选择: * (1)可以是任意类型的对象 * (2)必须是这几天线程要使用同一个锁对象 * * 锁的代码的范围的选择: * (1)太大了:不行 * (2)太小了:不行 * 锁一次任务 */ public class Test09 { public static void main(String[] args) { Ticket t1 = new Ticket("窗口一"); Ticket t2 = new Ticket("窗口二"); Ticket t3 = new Ticket("窗口三"); t1.start(); t2.start(); t3.start(); } } class Ticket extends Thread{ private static int total = 1000; private static Object lock = new Object();//锁的选择之一,单独造一个锁对象 public Ticket(String name) { super(name); } public void run(){ // synchronized (this) {//这里使用this不行,因为这个this,对于三个线程来说不是同一个 while(true){ synchronized (lock) { if(total > 0){ System.out.println(getName() + "卖出一张票"); total--; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("剩余:" + total); }else{ break; } } } } }
package com.atguigu.test10; /* * 步骤: * (1)编写线程类,实现Runnable * (2)重写run * (3)创建线程对象 * (4)启动线程 */ public class Test10 { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t,"窗口一"); Thread t2 = new Thread(t,"窗口二"); Thread t3 = new Thread(t,"窗口三"); t1.start(); t2.start(); t3.start(); } } class Ticket implements Runnable{ private int total = 10; @Override public void run() { while(true){ synchronized (this) {//选择this当锁,可以,因为只有一个Ticket的对象 if(total>0){ System.out.println(Thread.currentThread().getName() +"卖出一张票"); total--; System.out.println("剩余:" + total); }else{ break; } } } } }