前言
在上一章节中我们学习了JAVA 实现多线程的方式。在实际的开发过程中应用程序对线程应用和要求要比我们想象地要复杂。上节的两个例子只是简单地实现了多线程,但在线程安全上我们没有并没有做过多的思考和设计。
上节中的两个例子实现的多线程都具有一个特点:不论以那种方式实现的多线,线程与线程之间没有任何地联系,也不存在数据公用的问题。此时多线程的实现并不存在所谓的线程安全问题, 当在一些其他的场景中我们往往需要多个线程同时操作一个或者多个公用数据,此时多线程间将存在着线程安全问题。
典型地线程安全案例分析
首先我们通过一个简单的例子来说明多线程间的线程安全问题。
事例分析(基于继承Thread类的多线程的实现)
- 场景说明
现在在某售票厅有100张票,从第一张开始卖,分三个窗口出售,模拟一个客户购票结果。 代码实现
package coreJavaReview.thread; public class ThreadPurchaseTikect { public static void main(String[] args) { Purchanse p1 = new Purchanse(); Purchanse p2 = new Purchanse(); Purchanse p3 = new Purchanse(); p1.setName("第一个窗口"); p2.setName("第二个窗口"); p3.setName("第三个窗口"); p1.start(); p2.start(); p3.start(); } } class Purchanse extends Thread{ static int i = 1; public void run(){ while(true){ if(i<=100){ try { Thread.currentThread().sleep(1000); } catch (Exception e) { } System.out.println(Thread.currentThread().getName()+"出售了第"+i+"张票"); i++; } } } }
结果(部分结果)
第一个窗口出售了第97张票 第二个窗口出售了第97张票 第三个窗口出售了第97张票 第二个窗口出售了第100张票 第一个窗口出售了第100张票 第三个窗口出售了第101张票
问题分析
- 随着线程sleep的时间越长线程安全问题越明显:三个窗口能同一时间出售同一张票,最后还多买了一张票(第101张)。
- 场景说明
事例分析(基于实现Runnable接口的多线程的实现)
- 场景说明
现在在某售票厅有100张票,从第一张开始卖,分三个窗口出售,模拟一个客户购票结果。 代码示例
package coreJavaReview.thread; public class ThreadPurchaseTikectRunnable { public static void main(String[] args) { PurchaseTikectRunnbale p1 = new PurchaseTikectRunnbale(); PurchaseTikectRunnbale p2 = new PurchaseTikectRunnbale(); PurchaseTikectRunnbale p3 = new PurchaseTikectRunnbale(); Thread t1 = new Thread(p1); Thread t2 = new Thread(p2); Thread t3 = new Thread(p3); t1.setName("第一个窗"); t2.setName("第二个窗"); t3.setName("第三个窗"); t1.start(); t2.start(); t3.start(); } } class PurchaseTikectRunnbale implements Runnable{ static int i = 1; public void run(){ while(true){ if(i<=100){ try { Thread.currentThread().sleep(1000); } catch (Exception e) { } System.out.println(Thread.currentThread().getName()+"出售了第"+i+"张票"); i++; } } } }
结果(部分结果)
第二个窗出售了第97张票 第一个窗出售了第97张票 第三个窗出售了第99张票 第一个窗出售了第100张票 第二个窗出售了第100张票 第三个窗出售了第102张票
- 问题分析
- 随着线程sleep的时间越长线程安全问题越明显:三个窗口能同一时间出售同一张票,最后还多买了一张票(第101张)。
- 场景说明
问题小结
由上面两个事例我们可以看见在JAVA多线程中若多线程间操作同意数据将会出现线程安全问题(比如多个窗口买同一张票,错票等现象)