• 多线程(三)线程安全问题


    1.什么是线程安全?

    我们思考这么一个问题,假设有一部电影正在卖票,一共100张,用户即可以在app中购买,也可以在官网购买,也可以线下购买,那么有没有可能一个用户正在app买最后一张票,同时又有个人在官网购买,又有人在线下购买,这样就出现了多线程中的线程安全问题。我们来实例化下。

    1.创建任务

     1 public class Ticket implements Runnable {
     2     private int ticket=100;
     3     @Override
     4     public void run() {
     5         // TODO Auto-generated method stub
     6         while(true){
     7             if(ticket>0){
     8                 try {
     9                     Thread.sleep(50);//略微增加等待时间,表现实例
    10                 } catch (InterruptedException e) {
    11                     // TODO Auto-generated catch block
    12                     e.printStackTrace();
    13                 }
    14                 System.out.println(Thread.currentThread().getName()+"卖出了第"+ticket--+"张票");
    15             }
    16         }
    17     }
    18 }

    2.创建任务对象,执行任务

     1 public class demo01 {
     2     public static void main(String[] args) {
     3         //创建线程任务
     4         Ticket r = new Ticket();
     5         //创建线程对象
     6         Thread t1 = new Thread(r);
     7         Thread t2 = new Thread(r);
     8         Thread t3 = new Thread(r);
     9         //开启线程
    10         t1.start();
    11         t2.start();
    12         t3.start();
    13     }
    14 }

    执行结果:

    这就是问题所在,那么该如何解决这个问题?

    2. 同步代码块

     在使用是,要保证锁对象的唯一性。

    实际代码更改后

     1 public class Ticket01 implements Runnable {
     2     private int ticket=100;
     3     private Object obj = new Object();
     4     @Override
     5     public void run() {
     6         // TODO Auto-generated method stub
     7         while(true){
     8             //同步代码块
     9             synchronized (obj) {
    10                 if(ticket>0){
    11                     try {
    12                         Thread.sleep(50);
    13                     } catch (InterruptedException e) {
    14                         // TODO Auto-generated catch block
    15                         e.printStackTrace();
    16                     }
    17                     System.out.println(Thread.currentThread().getName()+"卖出了第"+ticket--+"张票");
    18                 }
    19             }
    20         }
    21     }
    22 }

    3.同步方法

    实际代码更改

     1 public class Ticket02 implements Runnable {
     2     private int ticket=100;
     3     @Override
     4     public void run() {
     5         // TODO Auto-generated method stub
     6         while(true){
     7             sale();
     8         }
     9     }
    10     public synchronized void sale(){
    11         if(ticket>0){
    12             try {
    13                 Thread.sleep(50);
    14             } catch (InterruptedException e) {
    15                 // TODO Auto-generated catch block
    16                 e.printStackTrace();
    17             }
    18             System.out.println(Thread.currentThread().getName()+"卖出了第"+ticket--+"张票");
    19         }
    20     }
    21 }

    4.Lock接口

    使用Lock接口,我们可以更广泛的锁定操作。

    实际代码更改

     1 public class Ticket03 implements Runnable {
     2     private int ticket=100;
     3     private Lock lock = new ReentrantLock();
     4     @Override
     5     public void run() {
     6         // TODO Auto-generated method stub
     7         while(true){
     8             lock.lock();
     9             if(ticket>0){
    10                 try {
    11                     Thread.sleep(50);
    12                 } catch (InterruptedException e) {
    13                     // TODO Auto-generated catch block
    14                     e.printStackTrace();
    15                 }
    16                 System.out.println(Thread.currentThread().getName()+"卖出了第"+ticket--+"张票");
    17             }
    18             lock.unlock();
    19         }
    20     }
    21 }
  • 相关阅读:
    win7下安装、使用jBuiler2006
    c#:使用using关键字自动释放资源未必一定就会有明显好处
    silverlight:ScrollViewer的各种高度研究
    silverlight:对象拖动的优雅解决方案
    民航货运英文缩写
    "RDLC"报表参数传递及主从报表
    "RDLC报表"速成指南
    打印常识:A4纸张在显示器上应该要多少像素?
    Silverlight:获取ContentTemplate中的命名控件
    Silverlight:双向绑定综合应用多集合的依赖绑定
  • 原文地址:https://www.cnblogs.com/shenhx666/p/15061998.html
Copyright © 2020-2023  润新知