模拟火车票售票程序:
1 /** 2 * 售票案例:售票的动作被多个线程同时执行 3 */ 4 class Ticket implements Runnable{ 5 //描述票的数量 6 private int tickets=100; 7 //售票,线程任务中通常都有循环结构 8 @Override 9 public void run() { 10 while(true) { 11 if(tickets>0) {//此处可能线程1,2,3,4都进入,那么就可能出现输出tickets为负值的错误数据 12 try { 13 Thread.sleep(200); 14 } catch (InterruptedException e) { 15 //待处理 16 } 17 System.out.println(Thread.currentThread().getName()+"------"+tickets--); 18 } 19 } 20 } 21 } 22 23 public class TicketSellDemo { 24 public static void main(String[] args) { 25 Ticket t=new Ticket(); 26 27 Thread t1=new Thread(t); 28 Thread t2=new Thread(t); 29 Thread t3=new Thread(t); 30 Thread t4=new Thread(t); 31 32 t1.start(); 33 t2.start(); 34 t3.start(); 35 t4.start(); 36 } 37 }
1、线程安全问题出现的原因:
(1)多个线程操作共享的数据;
(2)线程任务操作共享数据的代码有多条(多个运算)。
2、解决思路:
只要让一个线程在执行线程任务时将多条操作共享数据的代码执行完,在执行过程中,不要让其他线程参与运算。那么如何在代码中体现呢?java中解决此问题:
(1)通过代码块完成,这个代码块叫做同步代码块,使用关键字synchronized。
1 /** 2 * 售票案例:售票的动作被多个线程同时执行 3 */ 4 class Ticket implements Runnable{ 5 //描述票的数量 6 private int tickets=20; 7 //售票,线程任务中通常有循环结构 8 private Object obj=new Object();//用来处理安全问题 9 @Override 10 public void run() { 11 while(true) { 12 synchronized(obj) 13 { 14 if(tickets>0) { 15 try { Thread.sleep(200);} catch (InterruptedException e) {/*待处理*/} 16 System.out.println(Thread.currentThread().getName()+"------"+tickets--); 17 } 18 } 19 } 20 } 21 } 22 23 public class TicketSellDemo { 24 public static void main(String[] args) { 25 Ticket t=new Ticket(); 26 27 Thread t1=new Thread(t); 28 Thread t2=new Thread(t); 29 Thread t3=new Thread(t); 30 Thread t4=new Thread(t); 31 32 t1.start(); 33 t2.start(); 34 t3.start(); 35 t4.start(); 36 } 37 }