多线程学习之解决线程同步的实现方法

 一、卖票的多线程实现

需求:共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票

代码实现:

/*** @Author:kkoneone11* @name:SellTicket1* @Date:2023/8/26 11:32*/
public class SellTicket1 implements Runnable{private int tickets = 100;@Overridepublic void run() {while(true){if(tickets < 0){break;}else {try{Thread.sleep(100);}catch (Exception e){e.printStackTrace();}tickets--;System.out.println(Thread.currentThread().getName() + "票数还剩余" + tickets);}}}
}public class SellTicketDemo {public static void main(String[] args) {SellTicket1 st = new SellTicket1();Thread thread1 = new Thread(st, "窗口1");Thread thread2 = new Thread(st, "窗口2");Thread thread3 = new Thread(st, "窗口3");thread1.start();thread2.start();thread3.start();}
}

可以看到这种程序写法的问题有:

  • 相同的票出现了多次

  • 出现了负数的票  

 问题产生的原因分析:这种多线程共享的是同一份数据,线程执行的随机性导致的,可能在卖票过程中丢失cpu的执行权,导致出现问题

二、解决问题的方案

要解决这个问题实际上就是让程序没有安全问题,如何实现其实就是让每次操作的时候只能有一个线程执行成功即可,那么可以实现的方案如下:

同步代码块

实现方法:

synchronized(任意对象) { 多条语句操作共享数据的代码 
}

优缺点:

  • 好处:解决了多线程的数据安全问题

  • 弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率

实例:

public class SellTicket1 implements Runnable{private int tickets = 100;private Object obj = new Object();@Overridepublic void run() {while(true){synchronized (obj){//当线程进来的时候就会把这段代码锁起来if(tickets <= 0){break;}else {try{Thread.sleep(100);}catch (Exception e){e.printStackTrace();}tickets--;System.out.println(Thread.currentThread().getName() + "票数还剩余" + tickets);}}//到此处锁就会释放了}}
}public class SellTicketDemo {public static void main(String[] args) {SellTicket1 st = new SellTicket1();Thread thread1 = new Thread(st, "窗口1");Thread thread2 = new Thread(st, "窗口2");Thread thread3 = new Thread(st, "窗口3");thread1.start();thread2.start();thread3.start();}
}

同步方法

实现方法:

锁住的对象是:this

修饰符 synchronized 返回值类型 方法名(方法参数) { 方法体;
}

静态同步方法

实现方法:

锁住的对象是:类名.class

修饰符 static synchronized 返回值类型 方法名(方法参数) { 方法体;
}

实例:

public class SellTicket1 implements Runnable{private static int tickets = 100;@Overridepublic void run() {while(true){if("窗口一".equals(Thread.currentThread().getName())){//同步方法boolean b = synchronizedMthod();if(b){break;}}else if("窗口二".equals(Thread.currentThread().getName())){//同步代码块synchronized (SellTicket1.class){if(tickets == 0){break;}else{try{Thread.sleep(100);}catch (Exception e){e.printStackTrace();}tickets--;System.out.println(Thread.currentThread().getName() + "票数还剩余" + tickets);}}}}}private static synchronized boolean synchronizedMthod(){if(tickets == 0){return true;}else{try{Thread.sleep(100);}catch (Exception e){e.printStackTrace();}tickets--;System.out.println(Thread.currentThread().getName() + "票数还剩余" + tickets);return false;}}
}public class SellTicketDemo {public static void main(String[] args) {SellTicket1 st = new SellTicket1();Thread thread1 = new Thread(st, "窗口1");Thread thread2 = new Thread(st, "窗口2");Thread thread3 = new Thread(st, "窗口3");thread1.start();thread2.start();thread3.start();}
}

ReentrantLock()

如果我们想可以直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

方法名说明
void lock()获得锁
void unlock()释放锁

实例:

public class SellTicket1 implements Runnable{//票的数量private int tickets = 100;private Object obj = new Object();private ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {while (true) {//synchronized (obj){//多个线程必须使用同一把锁.try {lock.lock();if (tickets <= 0) {//卖完了break;} else {Thread.sleep(100);tickets--;System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + tickets + "张票");}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}// }}}
}public class SellTicketDemo {public static void main(String[] args) {SellTicket1 st = new SellTicket1();Thread thread1 = new Thread(st, "窗口1");Thread thread2 = new Thread(st, "窗口2");Thread thread3 = new Thread(st, "窗口3");thread1.start();thread2.start();thread3.start();}
}

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

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

相关文章

设计模式之八:迭代器与组合模式

有许多方法可以把对象堆起来成为一个集合&#xff08;Collection&#xff09;&#xff0c;比如放入数组、堆栈或散列表中。若用户直接从这些数据结构中取出对象&#xff0c;则需要知道具体是存在什么数据结构中&#xff08;如栈就用peek&#xff0c;数组[]&#xff09;。迭代器…

占领手机,银行App的隐秘战事

作者 | 辰纹 来源 | 洞见新研社 十几年前&#xff0c;银行用各类卡片塞满我们的钱包&#xff1b;如今&#xff0c;银行用各种App塞满我们的手机。 说出来可能很多人还不相信&#xff0c;民商智慧《2019银行业电子银行场景营销分析报告》就提到&#xff0c;在2019年3月时&…

Nginx详解 一:编译安装Nginx和Nginx模块

文章目录 1.HTTP 和 Nginx1.1 Socket套接字1.2 HTTP工作机制1.2.1一次http事务1.2.2 资源类型1.2.3提高HTTP连接性能 2. I/O模型2.1 I/O模型相关概念2.2 网络I/O模型2.2.1 **阻塞型** **I/O** 模型&#xff08;blocking IO&#xff09;2.2.2 **非阻塞型** **I/O** **模型** **(…

android 系统(20)---背光灯

图1 这是MTK 2011年的图&#xff0c;下面给出MT6575/6577中此部分的框架图&#xff1a; 图2 再来看更体现一些细节的框架图&#xff1a; 图3 由此可见光系统从上到下依次分为java APP层、java 框架层、本地层和驱动层。下面就来看APP层&#xff0c;先给出调节背光的应用界面…

Ubuntu16.04设置背光灯发亮快捷键

Ubuntu16.04设置背光灯发亮快捷键 分三步&#xff1a; 1.新建根目录 mkdir ~/bin2编辑背光灯控制开关的脚本文件 vim ~bin/ledctrl将以下内容复制 #!/bin/bash - # # # FILE: ledctrl # # USAGE: ./ledctrl # # DESCRIPTION: # # OPTIONS: …

Linux c++开发-02-g++命令行编译

有如下的文件目录结构 格式一 swap.h swap.cpp main.cpp 编译方法和结果如下&#xff1a; 格式二 swap.cpp main.cpp 使用命令&#xff1a;g main.cpp src/swap.cpp -o main.exe 解决方法使用参数 -I 格式三-将swap.cpp生成一个静态库然后链接到main.cpp中 生成…

C语言文件操作收尾【随机读写 + 结束判定 + 文件缓冲区】

全文目录 前言fseek 重定位位置指示器函数ftell 获取当前文件指示器的位置rewind 重置位置指示器文本文件和二进制文件文件读取结束的判定feof 和 ferror 文件缓冲区总结 前言 有了文件的顺序读写基础&#xff0c;那么肯定会好奇文件的随机读写&#xff0c;毕竟顺序读写对于有…

python抢票开发——设备预约助手实现

女朋友是药学院的&#xff0c;做实验时需要在特定的网站上进行设备预约&#xff0c;由于预约人数过多&#xff0c;从而导致从浏览器登录不进去或者登录进去预约失败等情况&#xff0c;所以我用python帮她写了一个抢位助手&#xff0c;让程序自动去进行位置预定&#xff0c;实测…

春节Python抢票神器,支持候补抢票真的无敌了

想要回家的小伙伴们,大概经历了一波抢票大战。 一年一度春运着实让人难熬 这次顺便把一个Python抢票工具,送到了GitHub趋势榜第一。 项目名很干脆,就是12306,来自名叫文贤平的程序员。 这很可能是全GitHub最德高望重的购票小助手了,功能一直在更新,且现已支持Python …

Java IO流动(实战操作)

目录 1 IO流原理2 IO流的分类3 输入、输出流代码示例4 小结5 文件在前后台之间传递 在Java中&#xff0c;IO流是一种用于处理输入和输出操作的机制。它提供了一种统一的方式来读取和写入数据&#xff0c;平日开发中在文件读写&#xff0c;网络通信&#xff0c;特定场景的数据库…

老话题,火车票抢票助手,简化版 (漏洞已经失效^_^)

用了“二杠”兄弟的工具测试了抢票&#xff0c;先举个大拇指。牛&#xff01;可是我实在看不惯他画的界面&#xff0c;而且需要认证和访问他服务器上的wcf服务。看到许多园友都号称“破解”了。我也请出"Reflector"神器&#xff0c;尝试了下。发现把源exe文件作为app…

python模拟火车订票系统_如何用python编写火车抢票助手

前几天跟朋友说打算写一个抢票助手&#xff0c;最后由于某些原因念头打消了。 可就在昨天晚上&#xff0c;才隐约记起一年前的自己曾经说过&#xff1a;一年后我一定要写一个12306的抢票助手&#xff01;瞬间激情澎湃&#xff0c;甚至已经是快临近凌晨时便开始动工&#xff0c;…

无涯教程-Python机器学习 - Based on human supervision函数

Python机器学习 中的 Based on human s - 无涯教程网无涯教程网提供https://www.learnfk.com/python-machine-learning/machine-learning-with-python-based-on-human-supervision.html

Yolo系列-yolov3

YOLO-V3 这张图讲道理真的过分了&#xff01;&#xff01;&#xff01;我不是针对谁&#xff0c;在座的各位都是 终于到V3了&#xff0c;最大的改进就是网络结构&#xff0c;使其更适合小目标检测特征做的更细致&#xff0c;融入多持续特征图信息来预测不同规格物体 先验框更丰…

java 分布式游戏服务器框架,集群游戏服务器框架,游戏服务器网关框架 ioGame 网络游戏服务器框架

网络游戏框架简介 ioGame 是一个由 java 语言编写的网络游戏服务器框架。支持 websocket、tcp &#xff0c;适用于全球同服、回合制游戏、策略游戏、即时战斗等游戏服务器的开发。具有高性能、稳定、易用易扩展、超好编程体验等特点。可做为 H5、手游、端游的 java 游戏服务器…

游戏服务器架构通识

前言 这节讲座里&#xff0c;我们将从游戏服务器发展的简单历程出发&#xff0c;鸟瞰一下目前大多数的游戏服务器架构。 这里尽可能的避免陷入细节的技术问题&#xff0c;而是从技术进化的结果状态&#xff0c;反推原始问题是什么。希望能通过这个过程&#xff0c;解释清楚游戏…

游戏服务器架构设计整理

文章目录 前言一、单进程多线程的服务器设计模式&#xff0c;只有一个进程&#xff0c;但一个进程包好多个线程二、多进程单线程的服务器设计模式&#xff0c;多个进程&#xff0c;每个进程只有一个线程1.早期的MMORPG服务器结构2.中期-用户分离集群式3.中后期数据分离集群式4.…

游戏服务器被攻击了怎么办?

随着互联网的发展&#xff0c;网民数量激增&#xff0c;电子游戏的普及&#xff0c;庞大的玩家数量必然推动游戏市场发展。游戏受到攻击是游戏开发者的痛点&#xff0c;DDOS攻击是流量攻击的一个总称&#xff0c;还包括SYN Flood、ACK Flood、UDP Flood、TCP Flood、ICMP Flood…

经典游戏服务器端架构

文章目录 一、 讨论的背景二、 游戏服务器架构的要素三、核心的三个架构四、 游戏服务器模型的进化历程五、分服模型1.模型描述2.调度架构1.单进程游戏服务器2.多进程游戏服务器 3.内存架构1.动态内存2.预分配内存 4.进程间通讯手段1.Socket通讯2.消息队列3.远程调用 5.容灾和扩…

哪家的云游戏服务器好?如何选择云游戏服务器?

现如今&#xff0c;不少行业领域都对云服务器有不少的需求&#xff0c;尤其是游戏行业&#xff0c;需要专门的云游戏服务器。目前市场上的云游戏服务器有很多种类型&#xff0c;那么&#xff0c;哪家的云游戏服务器好呢&#xff1f;如何选择云游戏服务器&#xff1f;下面就跟着…