java 同步锁synchronized 解决线程共享数据重复操作问题

news2024/10/5 18:26:11

我们先来写一个买票程序
我们先创建一个包 在包下创建两个类

customException 线程类 负责编写抢票的主要逻辑
参考代码如下

public class customException implements Runnable {
    private int tickets = 100;

    public void run () {
        while (tickets > 0){
            if(tickets > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                tickets--;
            }
        }
    }
}

text 测试类 用于实例化线程对象 并执行线程

public class text {
    public static void main(String args[]) {
        Runnable Runnable = new customException();
        Thread m1 = new Thread(Runnable,"客户");
        Thread m2 = new Thread(Runnable,"黄牛");
        Thread m3 = new Thread(Runnable,"导爷");
        m1.start();
        m2.start();
        m3.start();
    }
}

然后 我们运行代码
在这里插入图片描述
我们会发现 第一百张票被抢了三次

在这里插入图片描述
负一也出来啦 这就是我们要解决的问题 线程执行随机性导致同一张票出售多次

科普个知识

java有特意为此现象 定义了数据安全性的描述
在这里插入图片描述
那么 显然 我们不是一个单线程 而是多线程 第一条 我们是到达了不安全的条件的
我们有一个tickets共享数据 所以 第二个条件 我们也是达到了不安全条件的

第三个 我们确实是在线程中 操作了 tickets 共享数据 tickets –

所以 这三个条件我们都达到了不安全的条件

java提供了 synchronized 锁方法解决这个问题 接受一个对象参数
这里 我们将customException 的 run方法修改代码如下

public void run () {
   while (tickets > 0){
        synchronized (new Object()) {
            if(tickets > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                tickets--;
            }
        }
    }
}

此时 我们调用了synchronized 将操作公共数据的代码锁了起来 运行结果如下

在这里插入图片描述
但很明显 问题并没有解决 因为我们传递对象是在方法中定义的 每个线程进来 看到的锁都是不一样的

那么 我们可以写一个公共的对象来锁

customException类代码修改如下

public class customException implements Runnable {
    private int tickets = 100;
    private Object obj = new Object();

   public void run () {
        while (true){
            synchronized (obj) {
                if(tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                    tickets--;
                }
            }
        }
    }
}

这里我们直接定义了一个叫 obj 的公共对象 来定义同步锁

然后我们执行代码
在这里插入图片描述
在这里插入图片描述
可以看到 我们的数据已经是正常的执行了 这就解决了我们上述的问题

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

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

相关文章

【语音增强】多维谱自适应小波语音信号去噪【含Matlab源码 1972期】

⛄一、自适应小波语音信号去噪 1 引言 语音信号在传输过程中,容易受到环境噪声和其他语音的干扰,降低了语音通信质量,影响了语音处理系统工作。所以,语音的净化处理技术,在现代语音通信和数字音频广播系统中起到愈来愈…

特殊的转义字符—— \b 退格字符 ASCII 08

引入 我们在写 C 语言题目时,经常会碰见这样的输出 11 123 1236 123410如果用循环的话,这个加号是个大问题,如果直接用 printf("%d"),最后会多一个加号,用 printf("%d") 则前面会多一个加号。想…

Qt编写视频监控管理平台(支持海康/大华/宇视/华为/天地伟业/H264/H265等)

一、前言 海康大华等厂家自己的客户端软件,基本上都是支持自家的设备,不支持其他家的摄像机和硬盘录像机,并不是因为技术上做不到,这些大厂要实现支持兼容其他的家的(他们家的服务端或者收费的都是支持其他家的&#…

写个rpc调用,试试自己了解多少

什么是rpc rpc即是远程过程调用,简单来说就是调用其他服务的接口像调用自己的本地方法一样,通常我们的调用的时候不需要关心调用过程和底层的通信即可实现调用其他的服务; 大概流程就是服务模块双方都会向注册中心注册自己的服务&#xff0c…

开发工具vim

一、开发工具vim vim的安装:yum install -y vim 指令:vim --version可以查看当前的版本信息,没有弹出信息就是没有安装。 装的vim是没有相关配置文件的,配置文件需要后面自己装。 之前说过,vs2019是集成软件编译…

【畅购商城】购物车模块之修改购物车以及结算

目录 购物车操作:修改 分析 接口 后端实现:更新 前端实现:修改 前端实现:全选 后端实现:删除数据 结算 跳转页面 购物车操作:修改 分析 接口 PUT http://localhost:10010/cart-service/carts 后…

python数学基础——单词统计

这个练习使用的是英文的单词统计,使用split通过单词中间的空格来做区分,在遍历的过程中通过对【字典】类型进行【字典推导式】的处理来计算每个单词出现的频次。但是由于过程中我们通过re的正则表达式来替换掉了很多的符号,并没有替换成空&am…

【网页设计】web前端期末大作业html+css

🎉精彩专栏推荐👇🏻👇🏻👇🏻 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业…

Day12--自定义组件-渲染my-search组件的基本结构

1.自定义搜索组件 我的操作: 1》在uni_modules中右键新建uni_modules插件: 2》看看效果图: ************************************************************************************************************** 2.在分类页面的 UI 结构中&…

工作中常用的设计模式--策略模式

一般做业务开发,不太容易有大量使用设计模式的场景。这里总结一下在业务开发中使用较为频繁的设计模式。当然语言为Java,基于Spring框架。 1 策略模式(Strategy Pattern) 一个类的行为或方法,在运行时可以根据条件的不同,有不同的…

verilog练习——基础语法

目录 基础语法 VL1 四选一多路器 VL2 异步复位的串联T触发器 VL3 奇偶校验 VL4 移位运算与乘法 VL5 位拆分与运算 VL6 多功能数据处理器 VL7 求两个数的差值 VL8 使用generate…for语句简化代码 VL9 使用子模块实现三输入数的大小比较 VL10 使用函数实现数据大小端转…

数据结构题目收录(二十五)

1、排序趟数与序列的原始状态无关的排序方法是()。 Ⅰ、直接插入排序 Ⅱ、简单选择排序 Ⅲ、冒泡排序 Ⅳ、基数排序 A:Ⅰ、ⅢB:Ⅰ、Ⅱ、ⅣC:Ⅰ、Ⅱ、ⅢD:Ⅰ、Ⅳ 解析 交换类的排序,其趟数和…

GUI编程--PyQt5--QDiaglog

文章目录QDialogQFontDialogQColorDialogQFileDialogQInputDialogQDialog 对话框基类,继承QWidget;用于短期任务,分为模态、非模态 模态,阻塞在当前窗口;分为应用程序级别&窗口级别(仅阻塞关联的窗口&…

关于使用鼠标时间mouseMove拖拽元素及元素抖动的解决方案

最近在做一个画布相关的项目时有一个场景是移动画布,最先开始想到的是拖拽事件,但是用户希望元素是实时的变化,所以决定使用mouseMove事件来做。 思路 通过mouseDown事件确定鼠标按下的位置根据mouseMove事件来计算出鼠标相对初始状态的横向…

MySQL锁杂谈

【说明】 1.MySQL版本5.7.37 2.事务隔离级别 REPEATABLE-READ 3.表结构 Create Table: CREATE TABLE isolation_innodb (id bigint(20) NOT NULL AUTO_INCREMENT,name varchar(10) DEFAULT NULL,money int(11) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT4…

jsp库存管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 库存管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开 发,数据库为Mysql,使用ja…

VMware Cloud Director数据库操作

VMware Cloud Director 是一个云服务平台,以自助服务模式提供安全、隔离、弹性的虚拟数据中心计算、网络、存储和安全。在NFV整个架构中属于VIM层,与NFVI层(对VMware来说即vSphere虚拟化环境)对接获取虚拟化资源并提供给租户。 NF…

服务访问质量(QoS)——QoS技术概述与配置

作者简介:一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 目录 前言 一.QoS技术概述 1.QoS的应用需求 ①网络拥塞的影响&#xff1a…

【Linux】项目自动化构建工具:make/Makefile的使用

文章目录一、背景1、make和makefile是什么?2、为什么要使用make和makefile?二、原理1、使用make和makefile2、依赖关系和依赖方法3、具体原理4、项目清理一、背景 1、make和makefile是什么? make是一个命令,是一个解释makefile中指令的命令…

Linux项目:自主web服务器

文章目录项目描述Web与 http 发展史DNSURI URL URNHTTP 概述项目纲要项目架构套接字的封装HTTP服务启动日志信息与工具类请求、响应类读取请求读取请求行读取请求报头分析请求行分析请求报头读取正文构建响应预处理返回静态网页CGI机制CGI机制的基本概念CGI函数的实现子CGI程序…