售票问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| package windowSale;
public class WindowSale1 { public static int countTicket=10;
public static void main(String[] args) { Window1 window1 = new Window1(); Window1 window2 = new Window1(); Window1 window3 = new Window1(); window1.start(); window2.start(); window3.start(); } } class Window1 extends Thread{ boolean judge=true; @Override public void run(){ while (judge){ sell(); } } public void sell(){ if (WindowSale1.countTicket<=0){ judge=false; System.out.println("售票结束");
} else { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } WindowSale1.countTicket = WindowSale1.countTicket - 1; System.out.println(Thread.currentThread().getName() + "售卖一张票" + "还剩" + WindowSale1.countTicket); }
} }
|
三个窗口售卖,会发现我们的票数剩余0张还可以继续售卖。这是因为在我们的票数还有两张时,我们的1号窗口进来还没有进行减去操作,2号与3号都进来,导致2张票被买了三次。
线程同步机制
在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任意同一时刻,最多由一个线程访问,保证数据的完整性。
同步的具体方法
- synchronized(对象){//得到对象的锁,才能操作同步带代码
//需要被同步的代码},操作的必须是同一个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package windowSale;
public class WindowSale1 { public static void main(String[] args) { SellTicket sellTicket=new SellTicket(); Thread thread1=new Thread(sellTicket); Thread thread2=new Thread(sellTicket); Thread thread3=new Thread(sellTicket); thread1.start(); thread2.start(); thread3.start(); } } class SellTicket extends Thread{ int ticketNum=100; boolean judge=true; Object obj=new Object(); @Override public void run() { while (judge){ sell(); } } public void sell(){
synchronized (this.obj){ if (ticketNum<=0){ System.out.println("售票结束"); judge=false; } else { ticketNum--; System.out.println(Thread.currentThread().getName()+"售卖一张票,号数为"+(ticketNum+1)+"还剩"+ticketNum); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
|
- synchronized还可以放在方法声明中,表示整个方法为同步方法
public synchronized void m(String name){
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package windowSale;
public class WindowSale1 { public static void main(String[] args) { SellTicket sellTicket=new SellTicket(); Thread thread1=new Thread(sellTicket); Thread thread2=new Thread(sellTicket); Thread thread3=new Thread(sellTicket); thread1.start(); thread2.start(); thread3.start(); } } class SellTicket extends Thread{ int ticketNum=100; boolean judge=true; @Override public void run() { while (judge){ sell(); } } public void sell(){ if (ticketNum<=0){ System.out.println("售票结束"); judge=false; } else { ticketNum--; System.out.println(Thread.currentThread().getName()+"售卖一张票,号数为"+(ticketNum+1)+"还剩"+ticketNum); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }
|
此时发现没有超票售出,但是售票的顺序却不正确,而且其实内部已经发生了超卖现象,但是我们只不过用代码块掩盖 了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package windowSale;
public class WindowSale1 { public static void main(String[] args) { SellTicket sellTicket=new SellTicket(); Thread thread1=new Thread(sellTicket); Thread thread2=new Thread(sellTicket); Thread thread3=new Thread(sellTicket); thread1.start(); thread2.start(); thread3.start(); } } class SellTicket extends Thread{ int ticketNum=100; boolean judge=true; @Override public void run() { while (judge){ sell(); } } public synchronized void sell(){ if (ticketNum<=0){ System.out.println("售票结束"); judge=false; } else { ticketNum--; System.out.println(Thread.currentThread().getName()+"售卖一张票,号数为"+(ticketNum+1)+"还剩"+ticketNum); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }
|