zoukankan      html  css  js  c++  java
  • 多线程操作共享数据出现的安全问题(卖票案例)

    操作共享数据,线程不安全代码:

    package com.yonyou.sci.gateway.exec;
    
    public class SellTicket implements Runnable{
    
        private static int ticket = 1;
    
        @Override
        public void run () {
            while (true) {
                if (ticket > 0) {
                    try{
                        // 模拟在这个位置,线程的执行权限被其他线程抢走了
                        Thread.sleep(10);
                    }catch (Exception ex){}
    
                    System.out.println(Thread.currentThread().getName()+" 出售第 " + ticket-- +" 票");
                }
            }
            
        }
    
    }

    三个线程同时执行上面的任务:

    package com.yonyou.sci.gateway.exec;
    
    public class SellMain {
    
        public static void main (String[] args) {
            SellTicket st = new SellTicket();
    
            Thread t1 = new Thread(st);
            Thread t2 = new Thread(st);
            Thread t3 = new Thread(st);
    
            t1.start();t2.start();t3.start();
        }
    }

    结果:

    Thread-0 出售第 1 票
    Thread-2 出售第 0 票
    Thread-1 出售第 -1 票

    分析:

    备注:线程的执行并不是按照顺序执行的,哪个线程抢到CPU执行权限,就执行哪个线程,所以上面的线程名不是按照顺序的。

    1.Thread-0 抢到CPU执行权限、开始执行任务,判断剩余票数大于0,sleep后、线程Thread-1 开始执行;

    2.Thread-2 抢到CPU执行权限、开始执行任务,Thread-0 还没有运行到 ticket-- 代码,此时 ticket 还是为1,判断剩余票数大于0,sleep后、线程Thread-1 开始执行;

    3.Thread-1 抢到CPU执行权限、开始执行任务,Thread-0、Thread-2 都还没有运行到 ticket-- 代码,此时 ticket 还是为1,判断剩余票数大于0,sleep后、线程Thread-0 开始执行 ticket-- 代码,输出:Thread-0 出售第 1 票

    4.Thread-2 开始执行 ticket-- 代码,此时 Thread-0 已经运行 ticket-- 代码,ticket变量值为0,所以输出:Thread-2 出售第 0 票

    5.Thread-1 开始执行 ticket-- 代码,此时 Thread-0、Thread-2 已经运行 ticket-- 代码,ticket变量值为 -1,所以输出:Thread-1 出售第 -1 票;


    解决线程异步操作共享数据安全问题:

    方法一:增加 synchronized 代码块;

    方法二:在方法上增加 synchronized 关键字;

    方法三:使用 lock 锁;

    方法一实现代码:

    package com.yonyou.sci.gateway.exec;
    
    public class SellTicket implements Runnable{
    
        private static int ticket = 1;
    
        @Override
        public void run () {
            while (true) {
                synchronized (this){
                    if (ticket > 0) {
                        try{
                            // 模拟在这个位置,线程的执行权限被其他线程抢走了
                            Thread.sleep(10);
                        }catch (Exception ex){}
    
                        System.out.println(Thread.currentThread().getName()+" 出售第 " + ticket-- +" 票");
                    }
                }
            }
    
        }
    
    }

     方法三 lock 锁实现代码:

    线程类:

    package com.yonyou.sci.gateway.exec.lock;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class SellTicketLock implements Runnable{
    
        private int ticket = 1;
    
        private Lock lock = new ReentrantLock();
    
        @Override
        public void run () {
    
            while (true) {
                lock.lock();
                try{
                    if (ticket > 0) {
                        Thread.sleep(10);
                        System.out.println(Thread.currentThread().getName()+" 出售第 " + ticket-- +" 票");
                    }
                }catch (Exception ex){
                    System.out.println(ex.getMessage());
                }finally {
                    lock.unlock();
                }
    
    
            }
        }
    
    }

    执行线程:

    package com.yonyou.sci.gateway.exec.lock;
    
    public class SellLockMain {
    
        public static void main (String[] args) {
            SellTicketLock st = new SellTicketLock();
    
            Thread t1 = new Thread(st);
            Thread t2 = new Thread(st);
            Thread t3 = new Thread(st);
    
            t1.start();t2.start();t3.start();
        }
    }
  • 相关阅读:
    JS实现前台表格排序功能
    openoffice安装手记
    OpenOffice 实现OFFICE在线预览
    毫秒事件转换小方法
    axis2 jar包详解及缺少jar包异常分析
    Android EditText控件完美实现只读(ReadOnly/NonEditable)
    android:获取联系人信息(姓名和电话)
    dex2jar.bat反编译apk的classes.dex文件错误:
    服务器压力测试系列二:服务器监控工具tsar安装
    memcache list all keys
  • 原文地址:https://www.cnblogs.com/tangshengwei/p/11723649.html
Copyright © 2011-2022 走看看