【Java多线程】同步代码块处理线程安全问题

news2025/1/16 6:39:39
题:创建三个窗口卖票,总票数为100张
1.问题:买票过程中,出现了重票,错票 --> 出现了线程的安全问题
2.问题出现的原因:当某个线程操作车票的过程中,尚未操作完成时,其他线程参与进来,也操作车票
3.如何解决:当一个线程a在操作ticket的时候,其他线程不能参与进来,直到线程a操作完成ticket时,
  其他线程才可以开始操作ticket。这种情况即使线程a出现了阻塞,也不能被改变。
根据生活中的事情举例:
假如你在上厕所,另一个人很急,冲进了你所在的厕所。这就出现了安全问题。应该如何解决? 
答:把厕所门锁住
4.在Java中,我们通过同步机制,来解决线程的安全问题。
=======================================================================================
  方式一:同步代码块
   synchronized(同步监视器){
       //需要被同步的代码
   }
   说明: 1.操作共享数据的代码,即为需要被同步的代码
         2.共享数据:多个线程共同操作的变量。比如:ticket就是共享数据
         3.同步监视器。俗称:锁。任何一个类的对象,都可以充当锁
           要求:多个线程必须要共用同一把锁

 

同步代码块处理实现Runnable的线程安全问题

代码如下:

class Window1 implements Runnable{

    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj) {
                if (ticket > 0){
                    System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                }else {
                    break;
                }
            }
        }
    }
}
public class WindowTest1{
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

 根据多次运行也并未发现错票跟重票

同步代码块处理继承Thread类的线程安全问题

我们首先模仿上面的方法,运行测试;

代码如下:


class Window extends Thread{
    private static int ticket = 100;
    private Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj){
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName() + "卖票,票号为:" + ticket);
                    ticket --;
                }else {
                    break;
                }
            }
        }
    }
}
public class WindowTest {
    public static void main(String[] args) {
        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}
运行结果如图

我们可以看到还是有重票的。因为上文有描述到的。要求:多个线程必须要共用同一把锁
所以我们可以加上static
代码如下所示
class Window extends Thread{
    private static int ticket = 100;
    private static Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj){
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName() + "卖票,票号为:" + ticket);
                    ticket --;
                }else {
                    break;
                }
            }
        }
    }
}
public class WindowTest {
    public static void main(String[] args) {
        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}
运行就没有了问题。
=======================================================================================
我们看到“要求:多个线程必须要共用同一把锁”
同步代码块处理实现Runnable的线程安全问题中我们可以将同步监视器改为“this”
此时的this:唯一的Window1的对象
class Window1 implements Runnable{

    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (this){//此时的this:唯一的Window1的对象 synchronized (obj) {
                if (ticket > 0){
                    System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                }else {
                    break;
                }
            }
        }
    }
}
public class WindowTest1{
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}
思考一下在同步代码块处理继承Thread类的线程安全问题中是否也可以将同步监视器改为“this”
如下图所示
window创建了三个对象所以不能将同步监视器改为this。但是也有一个简便的方法,将同步监视器改为“Window.class”
synchronized (Window.class){
}
=======================================================================================
总结:
同步方式,解决了现成的安全问题。 ---好处
操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。---局限性
感谢观看!!!

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/198211.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA常用技巧汇总

查看代码历史版本鼠标在需要查看的java类 右键 找到Local History >> Show History 点开即可看到历史版本,常用于自己忘记代码改了哪些内容 或需要恢复至某个版本 (注意 只能看近期修改 太久了也是看不到的)idea设置成eclipse的快捷键这对eclipse转idea的开发…

网络编程套接字

✏️作者:银河罐头 📋系列专栏:JavaEE 🌲“种一棵树最好的时间是十年前,其次是现在” 目录Socket 套接字UDP 和 TCPUDP数据报套接字编程DatagramSocket APIDatagramPacket APIUdpEchoServerUdpEchoClientUdpDictServer…

分享62个JS返回顶部特效,总有一款适合您

分享62个JS返回顶部特效,总有一款适合您 62个JS返回顶部特效下载链接:https://pan.baidu.com/s/1X1fSwxibtEDXKeYqj0sHXQ?pwde2kp 提取码:e2kp Python采集代码下载链接:https://wwgn.lanzoul.com/iKGwb0kye3wj import os im…

[Android]Toolbar

Toolbar是由AndroidX库提供的,它的强大之处在于,它不仅继承了ActionBar的所有功能,并且灵活度很高,可以配合其他控件完成一些Material Design的效果。 使用Toolbar替代ActionBar 在themes的两个xml文件中, 都指定一个…

视频连载08 - 这个为生信学习和生信作图打造的开源R教程真香!!!

点击阅读原文跳转完整教案。1 思考题2 R基础2.1 R安装2.2 Rstudio基础2.2.1 Rstudio版本2.2.2 Rstudio安装2.2.3 Rstudio 使用2.3 R基本语法2.3.1 获取帮助文档,查看命令或函数的使用方法、事例或适用范围2.3.2 R中的变量及其初始化2.3.3 变量类型和转换2.3.4 R中矩…

ECharts接收dataset类型数据封装各类型图形组件

数据平台整合matabase图表,调用matabase已有接口使用echarts实现图表展示 目标 将各类型图形独立封装为组件 将多个组件整体封装成一个组件 使用时只需传入组件名和对应数据即可 展示 数据格式 ECharts中dataset配置 公共组件 示例饼图 pie-chart pie-chart comm…

AcWing 1083. Windy数(数位DP)

AcWing 1083. Windy数(数位DP)一、问题二、分析状态表示状态转移初末状态循环设计注意事项三、代码一、问题 二、分析 这道题考察的是数位DP的知识,对于数位DP的分析方法作者在之前的文章中做过详细地介绍:AcWing 1081. 度的数量…

java面试题(九)集合篇

2.1 Java中有哪些容器(集合类)? 参考答案 Java中的集合类主要由Collection和Map这两个接口派生而出,其中Collection接口又派生出三个子接口,分别是Set、List、Queue。所有的Java集合类,都是Set、List、Qu…

【LeetCode】Day206-二叉树着色游戏

题目 1145. 二叉树着色游戏【中等】 题解 官解说的实在是抽象了,看了下高赞题解,果然很清晰易懂 以 x 为根,它的三个邻居(左儿子、右儿子和父节点)就对应着三棵子树: 左子树右子树父节点子树 哪棵子树…

微服务项目框架及多模块开发

目录 项目模式 技术栈 项目架构图 模块 案例演示 主模块 zmall-common子模块 zmall-user子模块 项目模式 电商模式:市面上有5种常见的电商模式,B2B、B2C、 C2B、 C2C、O2O; 1、B2B模式 B2B (Business to Business),是指 商家与商家…

java递归-八皇后问题(回溯算法)

1.八皇后问题介绍 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯贝瑟尔于 1848 年提出:在 88 格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都…

Day04-数据分析模型

文章目录数据分析模型数据分析流程第一:定性法第二:定量法一、数据分析要解决什么问题?1. 研究历史2. 解释现状4. 洞察商机5. 寻求最佳方案二、数据分析师的工作三、数据分析流程1. 数据分析框架2. 数据获取3. 数据处理4. 数据分析5. 撰写报告…

大数据技术架构(组件)18——Hive:FileFormats(1)

1.5、FileFormats1.5.1、FileFormat对比:1.5.1.1、Text File每一行都是一条记录,每行都以换行符(\ n)结尾。数据不做压缩,磁盘开销大,数据解析开销大。可结合Gzip、Bzip2使用(系统自动检查&…

Python 3 基本数据类型,包含示例演示(初学友好)

嗨害大家好鸭~ 我是小熊猫 有好好学习python吗? Python学习资料电子书 点击此处跳转文末名片获取 Python3 基本数据类型 Python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。 在 Python 中,变量就是变量…

Redis实现分布式锁

基于Redis实现分布式锁。分为单Redis节点实现和Redis集群实现。 基于单个Redis节点实现分布式锁 作为分布式锁实现过程中的共享存储系统,Redis可以使用键值对来保护锁变量,在接收和处理不同客户端发送的加锁的操作请求。 客户端A、C同时请求加锁&#…

【Linux】基本开发工具的使用-yumvimgcc/g++git

文章目录Linux 软件包管理器-yum什么是软件包window和Linux互传文件的工具: lrzszyum注意事项查看软件包注意事项如何安装软件注意事项如何卸载软件好玩的指令sl 小火车cowsay 打印一只说话的小牛boxes 打印一个ASCII的动画linux_logo 显示linux系统的logocurl http://wttr.in …

2021美赛D题艺术家思路整理

问题整理 使用influence_data数据集或其部分创建音乐影响力的(多个)定向网络,其中影响者与关注者相连。开发捕捉此网络中“音乐影响的参数”。通过创建定向影响网络的子网络来探索音乐影响力的子集。描述这个子网络。你的“音乐影响”指标在…

((蓝桥杯 刷题全集)【备战(蓝桥杯)算法竞赛-第3天】( 从头开始重新做题,记录备战竞赛路上的每一道题 )距离蓝桥杯还有64天

🏆🏆🏆🏆🏆🏆🏆 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录&a…

PMP知识点1

根据PMBOK和参考书籍自己总结的一些不熟悉知识点,当做笔记放这复习。 1. 项目战略管理、组合管理、项目及管理、项目管理区别 战略管理项目组合管理项目集管理项目管理工作内容明确组织战略目标选择有利于实现战略目标的项目分析并利用各项目之间有机联系规范有序…

RAS《Research on Offense and Defense of DDos Based on Evolutionar Game Theory》

Read abstract and personal Summary of《Research on Offense and Defense of DDos Based on Evolutionar Game Theory》Ⅰ:Read abstract(阅读摘要)0:Proper noun interpretation(专有名词解释)1:The question raise…