如何判断一个程序是否会有线程安全问题?
/* * 如何解决线程安全问题呢? * * 要想解决问题,就要知道哪些原因会导致出问题:(而且这些原因也是以后我们判断一个程序是否会有线程安全问题的依据) * A:是否是多线程环境 * B:是否有共享数据 * C:是否有多条语句操作共享数据 * * 我们来回想一下我们的程序有没有上面的问题呢? * A:是否是多线程环境 是 * B:是否有共享数据 是 * C:是否有多条语句操作共享数据 是 * * 由此可见我们的程序出现问题是正常的,因为它满足出问题的条件。 * * 接下来才是我们要想想如何解决问题呢? * A和B的问题我们改变不了,我们只能想办法去把C问题改变一下。 * * * 思想: * 把多条语句操作共享数据的代码部分给包起来(锁起来),让某个线程在执行的时候,别人不能来执行。 * (即:把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可) * * 问题是:我们不知道怎么包啊?其实我也不知道啊!但是Java给我们提供了:同步机制。 * * 生活举例: * 火车上厕所。 * 医院挂号看病。 * * 同步代码块: * synchronized(对象) { * 需要同步的代码; * } * * A:对象是什么呢? * 我们可以随便创建一个对象先试试,例如:new Object()。 * B:需要同步的代码是哪些呢? * 把多条语句操作共享数据的代码部分给包起来(锁起来)。 * * 注意: * 同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。 * 多个线程必须是同一把锁。 * */
示例代码如下:
1 package cn.itcast_09; 2 3 /* 4 * 如何解决线程安全问题呢? 5 * 6 * 要想解决问题,就要知道哪些原因会导致出问题:(而且这些原因也是以后我们判断一个程序是否会有线程安全问题的依据) 7 * A:是否是多线程环境 8 * B:是否有共享数据 9 * C:是否有多条语句操作共享数据 10 * 11 * 我们来回想一下我们的程序有没有上面的问题呢? 12 * A:是否是多线程环境 是 13 * B:是否有共享数据 是 14 * C:是否有多条语句操作共享数据 是 15 * 16 * 由此可见我们的程序出现问题是正常的,因为它满足出问题的条件。 17 * 18 * 接下来才是我们要想想如何解决问题呢? 19 * A和B的问题我们改变不了,我们只能想办法去把C问题改变一下。 20 * 21 * 22 * 思想: 23 * 把多条语句操作共享数据的代码部分给包起来(锁起来),让某个线程在执行的时候,别人不能来执行。 24 * (即:把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可) 25 * 26 * 问题是:我们不知道怎么包啊?其实我也不知道啊!但是Java给我们提供了:同步机制。 27 * 28 * 生活举例: 29 * 火车上厕所。 30 * 医院挂号看病。 31 * 32 * 同步代码块: 33 * synchronized(对象) { 34 * 需要同步的代码; 35 * } 36 * 37 * A:对象是什么呢? 38 * 我们可以随便创建一个对象先试试,例如:new Object()。 39 * B:需要同步的代码是哪些呢? 40 * 把多条语句操作共享数据的代码部分给包起来(锁起来)。 41 * 42 * 注意: 43 * 同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。 44 * 多个线程必须是同一把锁。 45 * 46 */ 47 public class SellTicketDemo { 48 public static void main(String[] args) { 49 // 创建资源对象 50 SellTicket st = new SellTicket(); 51 52 // 创建三个线程对象 53 Thread t1 = new Thread(st, "窗口1"); 54 Thread t2 = new Thread(st, "窗口2"); 55 Thread t3 = new Thread(st, "窗口3"); 56 57 // 启动线程 58 t1.start(); 59 t2.start(); 60 t3.start(); 61 } 62 }
1 package cn.itcast_09; 2 3 public class SellTicket implements Runnable { 4 // 为了让多个线程对象共享这100张票和锁对象(同一把锁),我们应该用静态修饰。 5 // 定义100张票 6 private int tickets = 100; 7 // 创建锁对象 8 private Object obj = new Object(); 9 10 /* 11 @Override 12 public void run() { 13 while (true) { 14 synchronized(new Object()){ // 我们可以随便创建一个对象先试试,例如:new Object()。 15 if (tickets > 0) { 16 try { 17 Thread.sleep(100); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); 22 } 23 } 24 } 25 } 26 */ 27 28 @Override 29 public void run() { 30 while (true) { 31 synchronized (obj) { 32 if (tickets > 0) { 33 try { 34 Thread.sleep(100); 35 } catch (InterruptedException e) { 36 e.printStackTrace(); 37 } 38 System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); 39 } 40 } 41 } 42 } 43 }