ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

线程安全问题的概述与线程安全问题的代码实现

2022-07-07 21:02:35  阅读:148  来源: 互联网

标签:Thread start 卖票 安全 线程 new 概述


线程安全

如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
我们通过一个案例,演示线程的安全问题:
电影院要卖票,我们模拟电影院的卖票过程。假设要播放的电影是“葫芦娃大战奥特曼”,本次电影的座位共100个(本场电影只能卖100张票)。
我们来模拟电影院的售票窗口,实现多个窗口同时卖“葫芦娃大战奥特曼"这场电影票(多个窗口一起卖这100张票)需要窗口,采用线程对象来模拟;需要票,Runnable接口子类来模拟

 

二、简介
1.什么是线程安全?
(1)控制多个线程对某个资源的有序访问或修改
(2)如果一个类在多线程的访问下,其状态是可以 预测的,并且不需要额外的同步,那么这个类 就是线程安全的类
2. 为什么要线程安全?
(1) 线程不安全会造成数据错误,修正数据错误是 费时费力的
(2) 线程不安全会导致程序发生一些异常行为,而 且这种行为很难查找
(3) 线程不安全的现象一般只有在并发量大时才会 出现,因此很难重现

三、 线程不安全产生原因
1.线程工作内存与主存交互
当线程操作某个共享变量时,可能的执行顺序如下:
(1)从主存复制变量到当前工作内存
(2)执行代码,改变共享变量的值
(3) 将工作内存数据同步回主存
2. 内存可见性与互斥性
(1)可见性:一个线程的执行结果可以被另一个线程 所看到
(2)互斥性:在同一时间只能有一个线程对变量的主 存进行操作

package Demo01_Sleep;

/*
    实现卖票案例
*/
public class RunnableImpl implements Runnable{
    // 定义一个多线程贡献的票源
    private int ticket = 100;
    // 设置线程任务:卖票
    @Override
    public void run() {
        // 使用死循环 让卖票操作重复执行
        while (true){
            // 先判断票是否存在
            if (ticket >= 0){
                // 使用线程睡眠提高安全问题出现的概率
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 卖票
                System.out.println("在卖"+Thread.currentThread().getName()+"线程的第:"+ticket+"张票");
                ticket--;
            }
        }
    }
}

/* 
    模拟卖票案例
    创建了3个共享线程,同时开启,对共享的票进行出售
*/
class Demo01Ticket {
    public static void main(String[] args) {
        // 创建实现类对象
        RunnableImpl runnable = new RunnableImpl();
        // 创建Thread类对象,构造方法中传递Runnable接口的实现类
        Thread thread0 = new Thread(runnable);
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        // 调用start开启多线程
        thread0.start();
        thread1.start();
        thread2.start();
    }
}

 

package Demo01_Sleep;

public class SellTicket implements Runnable {
    private int tickets = 100;
    //在SellTicket类中重写run()方法实现卖票,代码步骤如下
    @Override
    public void run() {
        while (true) {
            if (tickets > 0) {
                System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                tickets--;
            }
        }
    }
}
class SellTicketDemo {
    public static void main(String[] args) {
        //创建SellTicket类的对象
        SellTicket st = new SellTicket();

        //创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
        Thread t1 = new Thread(st,"窗口1");
        Thread t2 = new Thread(st,"窗口2");
        Thread t3 = new Thread(st,"窗口3");

        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

 

标签:Thread,start,卖票,安全,线程,new,概述
来源: https://www.cnblogs.com/x3449/p/16456116.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有