java 多线程学习笔记之 线程互斥

2023-11-09

许多线程共享同一数据,这种情况在现实的生活中也是经常发生的,比如火车站的火车票售票系统。火车票售票系统是一个常年运行的系统,为了满足乘客的需求,我们不能只设一个窗口,必须设很多的售票窗口,每个售票窗口就像一个线程,它们各自运行,共同访问相同的数据——火车票的数量,下面我们用多线程模仿一下火车票售票系统:

相关测试代码:

package com.example.ticker;

public class Ticker {
	// 初始化火车票数量
	private int tickers = 0;

	public int getTickers() {
		return tickers;
	}

	public void setTickers(int tickers) {
		this.tickers = tickers;
	}

	// 初始化构造函数
	public Ticker(int tickers) {
		super();
		this.tickers = tickers;
	}

	// 售票方法
	public void sell() {

		if (tickers > 0) {
			System.out.println("sell tickets:" + tickers);
			tickers--;
		}

	}

}
package com.examplex.threadstate;

import com.example.ticker.Ticker;

public class TicketRunnable implements Runnable {
	private Ticker ticker;
	private String name;

	public Ticker getTicker() {
		return ticker;
	}

	public void setTicker(Ticker ticker) {
		this.ticker = ticker;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public TicketRunnable(String name, Ticker ticker) {
		super();
		this.ticker = ticker;
		this.name = name;
	}

	@Override
	public void run() {
		// 死循环
		while (true) {
			// 条件判断
			if (ticker.getTickers() > 0) {
				System.out.println("当前线程为:" + this.name);
				ticker.sell();
			}

		}

	}

}
package com.example.main;

import com.example.ticker.Ticker;
import com.examplex.threadstate.MyRunnable;
import com.examplex.threadstate.MyThread;
import com.examplex.threadstate.TicketRunnable;

public class TestMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Ticker ticker = new Ticker(100);

		Thread thread1 = new Thread(new TicketRunnable("线程一", ticker));
		Thread thread2 = new Thread(new TicketRunnable("线程二", ticker));
		Thread thread3 = new Thread(new TicketRunnable("线程三", ticker));
		Thread thread4 = new Thread(new TicketRunnable("线程四", ticker));

		thread1.start();
		thread2.start();
		thread3.start();
		thread4.start();

	}

}

相关测试结果:

当前线程为:线程一
sell tickets:100
当前线程为:线程一
当前线程为:线程三
sell tickets:99
当前线程为:线程一
sell tickets:98
当前线程为:线程一
sell tickets:97
当前线程为:线程一
sell tickets:96
当前线程为:线程一
sell tickets:95
当前线程为:线程一
sell tickets:94
当前线程为:线程一
sell tickets:93
当前线程为:线程一
sell tickets:92
当前线程为:线程一
sell tickets:91
当前线程为:线程一
sell tickets:90
当前线程为:线程一
sell tickets:89
当前线程为:线程一
sell tickets:88
当前线程为:线程一
sell tickets:87
当前线程为:线程一
sell tickets:86
当前线程为:线程一
sell tickets:85
当前线程为:线程一
sell tickets:84
当前线程为:线程一
sell tickets:83
当前线程为:线程一
sell tickets:82
当前线程为:线程一
sell tickets:81
当前线程为:线程一
sell tickets:80
当前线程为:线程一
sell tickets:79
当前线程为:线程一
sell tickets:78
当前线程为:线程一
sell tickets:77
当前线程为:线程一
sell tickets:76
当前线程为:线程一
sell tickets:75
当前线程为:线程一
sell tickets:74
当前线程为:线程一
sell tickets:73
当前线程为:线程一
sell tickets:72
当前线程为:线程一
sell tickets:71
当前线程为:线程一
sell tickets:70
当前线程为:线程一
sell tickets:69
当前线程为:线程一
sell tickets:68
当前线程为:线程一
sell tickets:67
当前线程为:线程一
sell tickets:66
当前线程为:线程一
sell tickets:65
当前线程为:线程一
sell tickets:64
当前线程为:线程一
sell tickets:63
当前线程为:线程一
sell tickets:62
当前线程为:线程一
sell tickets:61
当前线程为:线程一
sell tickets:60
当前线程为:线程一
sell tickets:59
当前线程为:线程一
sell tickets:58
当前线程为:线程一
sell tickets:57
当前线程为:线程一
sell tickets:56
当前线程为:线程一
sell tickets:55
当前线程为:线程一
sell tickets:54
当前线程为:线程一
sell tickets:53
当前线程为:线程一
sell tickets:52
当前线程为:线程一
sell tickets:51
当前线程为:线程一
sell tickets:50
当前线程为:线程一
sell tickets:49
当前线程为:线程一
sell tickets:48
当前线程为:线程一
sell tickets:47
当前线程为:线程一
当前线程为:线程四
sell tickets:46
当前线程为:线程一
sell tickets:45
当前线程为:线程一
sell tickets:44
当前线程为:线程一
当前线程为:线程二
sell tickets:43
当前线程为:线程二
sell tickets:42
当前线程为:线程二
sell tickets:41
当前线程为:线程二
sell tickets:40
当前线程为:线程二
sell tickets:39
当前线程为:线程二
sell tickets:38
当前线程为:线程二
sell tickets:37
当前线程为:线程二
sell tickets:36
当前线程为:线程二
sell tickets:35
当前线程为:线程二
sell tickets:34
当前线程为:线程二
sell tickets:33
当前线程为:线程二
sell tickets:32
当前线程为:线程二
sell tickets:31
当前线程为:线程二
sell tickets:30
当前线程为:线程二
sell tickets:29
当前线程为:线程二
sell tickets:28
当前线程为:线程二
sell tickets:27
当前线程为:线程二
sell tickets:26
当前线程为:线程二
sell tickets:25
当前线程为:线程二
sell tickets:24
当前线程为:线程二
sell tickets:23
当前线程为:线程二
sell tickets:22
当前线程为:线程二
sell tickets:21
当前线程为:线程二
sell tickets:20
sell tickets:99
当前线程为:线程三
sell tickets:18
当前线程为:线程三
sell tickets:17
当前线程为:线程三
sell tickets:16
当前线程为:线程三
sell tickets:15
当前线程为:线程三
sell tickets:14
当前线程为:线程三
sell tickets:13
当前线程为:线程三
sell tickets:12
当前线程为:线程三
sell tickets:11
当前线程为:线程三
sell tickets:10
当前线程为:线程三
sell tickets:9
当前线程为:线程三
sell tickets:8
当前线程为:线程三
sell tickets:7
当前线程为:线程三
sell tickets:6
当前线程为:线程三
sell tickets:5
当前线程为:线程三
sell tickets:4
当前线程为:线程三
sell tickets:3
当前线程为:线程三
sell tickets:2
当前线程为:线程三
sell tickets:1
当前线程为:线程二
sell tickets:43
sell tickets:43

程序输出了线程0、1、2、4四个线程从第100张票卖到第1张票的过程,存在火车票多次重复出售的问题,这是在实际火车票出售中,是绝对不允许出现这样的问题。遇到了不对的情况,我们就应该得想办法解决它,在Java中运用互斥的方法解决这个问题。

什么叫互斥?

多线程同时共享同一数据(内存区域),每个线程都尝试操作该数据,从而导致数据被破坏,这种现象称为争用条件(互斥)。

java 如何解决互斥问题?

互斥操作的控制,Java提供了关键字synchronized进行的。synchronized可以修饰方法,也可以修饰代码段。其代表的含义就是:进入他修饰的这段代码内的线程必须先去获取一个特定对象的锁定标示,并且虚拟机保证这个标示一次只能被一条线程拥有。


进过上面的描述,来进行修改我们的Ticker类

package com.example.ticker;

public class Ticker {
	//初始化火车票数量
	private int tickers=0;
	
	private Object lock=new Object();

	public int getTickers() {
		return tickers;
	}

	public void setTickers(int tickers) {
		this.tickers = tickers;
	}
	//初始化构造函数
	public Ticker(int tickers) {
		super();
		this.tickers = tickers;
	}
	
	//售票方法
	public void sell(){
		synchronized(lock){
			if(tickers>0){
				System.out.println("sell tickets:"+tickers);
				tickers--;
			}
		}
		
	}
	
	
	

}
演示结果:
当前线程为:线程一
sell tickets:100
当前线程为:线程一
sell tickets:99
当前线程为:线程二
sell tickets:98
当前线程为:线程二
sell tickets:97
当前线程为:线程二
sell tickets:96
当前线程为:线程二
sell tickets:95
当前线程为:线程二
sell tickets:94
当前线程为:线程二
sell tickets:93
当前线程为:线程二
sell tickets:92
当前线程为:线程二
sell tickets:91
当前线程为:线程二
sell tickets:90
当前线程为:线程二
sell tickets:89
当前线程为:线程二
sell tickets:88
当前线程为:线程二
sell tickets:87
当前线程为:线程二
sell tickets:86
当前线程为:线程二
sell tickets:85
当前线程为:线程二
sell tickets:84
当前线程为:线程二
sell tickets:83
当前线程为:线程二
sell tickets:82
当前线程为:线程二
sell tickets:81
当前线程为:线程二
sell tickets:80
当前线程为:线程二
sell tickets:79
当前线程为:线程二
sell tickets:78
当前线程为:线程二
sell tickets:77
当前线程为:线程二
当前线程为:线程一
sell tickets:76
当前线程为:线程二
sell tickets:75
当前线程为:线程一
sell tickets:74
当前线程为:线程二
sell tickets:73
当前线程为:线程一
sell tickets:72
当前线程为:线程二
sell tickets:71
当前线程为:线程一
sell tickets:70
当前线程为:线程二
sell tickets:69
当前线程为:线程一
当前线程为:线程四
当前线程为:线程三
sell tickets:68
当前线程为:线程二
sell tickets:67
当前线程为:线程二
sell tickets:66
当前线程为:线程二
sell tickets:65
当前线程为:线程二
sell tickets:64
当前线程为:线程二
sell tickets:63
当前线程为:线程二
sell tickets:62
当前线程为:线程二
sell tickets:61
当前线程为:线程二
sell tickets:60
当前线程为:线程二
sell tickets:59
当前线程为:线程二
sell tickets:58
当前线程为:线程二
sell tickets:57
当前线程为:线程二
sell tickets:56
当前线程为:线程三
sell tickets:55
当前线程为:线程四
sell tickets:54
当前线程为:线程一
sell tickets:53
当前线程为:线程四
sell tickets:52
当前线程为:线程三
sell tickets:51
当前线程为:线程二
sell tickets:50
当前线程为:线程三
sell tickets:49
当前线程为:线程四
sell tickets:48
当前线程为:线程一
sell tickets:47
当前线程为:线程四
sell tickets:46
当前线程为:线程三
sell tickets:45
当前线程为:线程三
sell tickets:44
当前线程为:线程三
sell tickets:43
当前线程为:线程三
sell tickets:42
当前线程为:线程三
sell tickets:41
当前线程为:线程三
sell tickets:40
当前线程为:线程三
sell tickets:39
当前线程为:线程三
sell tickets:38
当前线程为:线程三
sell tickets:37
sell tickets:36
当前线程为:线程二
sell tickets:35
当前线程为:线程二
sell tickets:34
当前线程为:线程二
sell tickets:33
当前线程为:线程二
sell tickets:32
当前线程为:线程二
sell tickets:31
当前线程为:线程二
sell tickets:30
当前线程为:线程二
sell tickets:29
当前线程为:线程二
sell tickets:28
当前线程为:线程二
sell tickets:27
当前线程为:线程二
sell tickets:26
当前线程为:线程二
sell tickets:25
当前线程为:线程二
sell tickets:24
当前线程为:线程二
sell tickets:23
当前线程为:线程二
sell tickets:22
当前线程为:线程二
sell tickets:21
当前线程为:线程二
sell tickets:20
当前线程为:线程二
sell tickets:19
当前线程为:线程二
sell tickets:18
当前线程为:线程二
sell tickets:17
当前线程为:线程二
sell tickets:16
当前线程为:线程二
sell tickets:15
当前线程为:线程二
sell tickets:14
当前线程为:线程二
sell tickets:13
当前线程为:线程二
当前线程为:线程三
sell tickets:12
当前线程为:线程四
sell tickets:11
当前线程为:线程一
sell tickets:10
当前线程为:线程四
sell tickets:9
当前线程为:线程三
sell tickets:8
当前线程为:线程二
sell tickets:7
当前线程为:线程三
sell tickets:6
当前线程为:线程四
sell tickets:5
当前线程为:线程一
sell tickets:4
当前线程为:线程四
sell tickets:3
当前线程为:线程三
sell tickets:2
当前线程为:线程二
sell tickets:1

以上结果才算是正确的。

今天已经完成java 多线程学习之(互斥),下一讲,准备说(java 多线程之同步)


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 多线程学习笔记之 线程互斥 的相关文章

  • Java线程:volatile关键字

    本文转载至 http lavasoft blog 51cto com 62575 222076 Java线程 volatile关键字 Java 语言包含两种内在的同步机制 同步块 或方法 和 volatile 变量 这两种机制的提出都是为了
  • java并发包:读写锁

    本文转载至 http blog csdn net a910626 article details 51900954 ReadWriteLock是jdk5中提供的读写分离锁 读写分离锁可以有效的帮助减少锁竞争 以提升性能 用锁分离的机制来提升
  • Java线程:线程的同步-同步方法

    本文转载至 http lavasoft blog 51cto com 62575 221914 Java线程 线程的同步 同步方法 线程的同步是保证多线程安全访问竞争资源的一种手段 线程的同步是Java多线程编程的难点 往往开发者搞不清楚什
  • Java线程:线程的交互

    本文转载至 http lavasoft blog 51cto com 62575 99157 线程交互是比较复杂的问题 SCJP要求不很基础 给定一个场景 编写代码来恰当使用等待 通知和通知所有线程 一 线程交互的基础知识 SCJP所要求的
  • Java线程:线程栈模型与线程的变量

    本文转载至 http lavasoft blog 51cto com 62575 99152 要理解线程调度的原理 以及线程执行过程 必须理解线程栈模型 线程栈是指某时刻时内存中线程调度的栈信息 当前调用的方法总是位于栈顶 线程栈的内容是随
  • Java线程:新特征-障碍器

    本文转载至 http lavasoft blog 51cto com 62575 222738 Java5中 添加了障碍器类 为了适应一种新的设计需求 比如一个大型的任务 常常需要分配好多子任务去执行 只有当所有子任务都执行完成时候 才能执
  • java并发包:概论

    本文转载至 http blog csdn net a910626 article details 51900917 为什么要学习并发 今天和一哥们聊天 聊着聊着聊到钱的方面 当时我就说 全世界60亿人 要是每人给我一块钱那不就发财了啊 哥们
  • Java线程:并发协作-死锁

    本文转载至 http lavasoft blog 51cto com 62575 222074 Java线程 并发协作 死锁 线程发生死锁可能性很小 即使看似可能发生死锁的代码 在运行时发生死锁的可能性也是小之又小 发生死锁的原因一般是两个
  • Java线程:新特征-有返回值的线程

    本文转载至 http lavasoft blog 51cto com 62575 222082 在Java5之前 线程是没有返回值的 常常为了 有 返回值 破费周折 而且代码很不好写 或者干脆绕过这道坎 走别的路了 现在Java终于有可返回
  • java 多线程学习笔记之 线程互斥

    许多线程共享同一数据 这种情况在现实的生活中也是经常发生的 比如火车站的火车票售票系统 火车票售票系统是一个常年运行的系统 为了满足乘客的需求 我们不能只设一个窗口 必须设很多的售票窗口 每个售票窗口就像一个线程 它们各自运行 共同访问相同
  • Java线程:新特征-信号量

    本文转载至 http lavasoft blog 51cto com 62575 222469 Java线程 新特征 信号量 Java的信号量实际上是一个功能完毕的计数器 对控制一定资源的消费与回收有着很重要的意义 信号量常常用于多线程的代
  • Java线程:线程的调度-守护线程

    本文转载至 http lavasoft blog 51cto com 62575 221845 Java线程 线程的调度 守护线程 守护线程与普通线程写法上基本么啥区别 调用线程对象的方法setDaemon true 则可以将其设置为守护线
  • java并发包:生产者消费者模式

    本文转载至 http blog csdn net a910626 article details 51900974 生产者消费者模式是一个经典的多线程设计模式 它为多线程间的协作提供了良好的解决方案 在生产者消费者模式中 通常有两类线程 即
  • Java线程:线程状态的转换

    本文转载至 http lavasoft blog 51cto com 62575 99153 一 线程状态类型 1 新建状态 New 新创建了一个线程对象 2 就绪状态 Runnable 线程对象创建后 其他线程调用了该对象的start 方
  • java并发包:重入锁与Condition条件

    本文转载至 http blog csdn net a910626 article details 51900941 重入锁 这里介绍一下synchronized wait notify方法的替代品 或者说是增强版 重入锁 重入锁是可以完全替
  • java 多线程学习笔记之 线程同步

    在前面我们将了很多关于同步的问题 然而在现实中 需要线程之间的协作 比如说最经典的生产者 消费者模型 当队列满时 生产者需要等待队列有空间才能继续往里面放入商品 而在等待的期间内 生产者必须释放对临界资源 即队列 的占用权 因为生产者如果不
  • Java线程:新特征-阻塞栈

    本文转载至 http lavasoft blog 51cto com 62575 222530 对于阻塞栈 与阻塞队列相似 不同点在于栈是 后入先出 的结构 每次操作的是栈顶 而队列是 先进先出 的结构 每次操作的是队列头 这里要特别说明一
  • Java线程:线程的调度-休眠

    本文转载至 http lavasoft blog 51cto com 62575 221790 Java线程 线程的调度 休眠 Java线程调度是Java多线程的核心 只有良好的调度 才能充分发挥系统的性能 提高程序的执行效率 这里要明确的
  • java 多线程学习笔记之 线程实现(线程阻塞)

    java 实现线程方法主要分为两种方法 一种是继承 java lang Thread 另一种实现java lang Runnable接口 对于直接继承Thread 的类来说 代码大致框架是 public class MyThread ext
  • java并发包:fork/join

    本文转载至 http blog csdn net a910626 article details 51900967 Fork Join框架是Java7提供了的一个用于并行执行任务的框架 是一个把大任务分割成若干个小任务 最终汇总每个小任务结

随机推荐

  • PHP的弱类型比较

    php弱类型比较 php中其中两种比较符号 先将字符串类型转化成相同 再比较 先判断两种字符串的类型是否相等 再比较 前者为弱比较 后者为弱比较 若在某种情况下不注意利用会导致漏洞的出现 例子 攻防世界lottery 进入页面 浏览后查看
  • android studio常用快捷键设置

    android开发工具androidstudio的熟练使用是提高我们开发效率的必备条件 现对android studio使用过程中的一些小技巧进行总结 1 命名规范 android开发过程中使用java语言 对变量的命名遵循驼峰命名法 一般
  • Tracy JS 小笔记 - 数据类型, typeof,类型转换

    数据类型 原始值 引用值 原始值 不可改变的原始值 是存储在栈里面 stack 是个有底儿的箱子结构先进后出 原始值 分为五大类 Number Boolean String undefined null var a 1 我们数据的类型天生就
  • Apache Pig的一些基础概念及用法总结4(转)

    26 错误 ERROR org apache pig tools grunt Grunt ERROR 2042 Error in new logical plan Try Dpig usenewlogicalplan false 的可能原因
  • decltype和declval的用法

    1 decltype是c 11以后出现的一个新的关键字 是用来萃取表达式或者变量或者函数返回值的类型的 具体用法可以参考官网 https en cppreference com w cpp language decltype 2 declv
  • 华为-人民币转换

    java实现 题目描述 考试题目和要点 1 中文大写金额数字前应标明 人民币 字样 中文大写金额数字应用壹 贰 叁 肆 伍 陆 柒 捌 玖 拾 佰 仟 万 亿 元 角 分 零 整等字样填写 2 中文大写金额数字到 元 为止的 在 元 之后
  • xss基础知识点

    xss 1 概念 跨站脚本攻击 英文全称Cross Site Script xss攻击 通常指黑客通过 HTML注入 篡改了网页 插入了恶意的脚本 从而在用户浏览网页时 控制用户浏览器的一种攻击 常见场景 标签内的xss Xss 属性里面的
  • 安装Flutter + Android sdk + vs code运行Flutter项目(史上最详解)

    前言 Flutter开发app是基于Dart语言开发的 就好比html网页开发基于JavaScript一样 而浏览器内核都可以编译JavaScript代码 所有开发html网页不需要下载啥SDK 直接在浏览器就能运行 首先我们安装Dart语
  • python 用for i in range(10)生成列表

    这种方法叫列表解析 1 列出1 10的平方和 结果用列表存储 要求 列出1 10所有数字的平方 1 普通方法 L for i in range 1 11 L append i 2 print L 1 4 9 16 25 36 49 64 8
  • 如何实现通用分页(来看我这一篇就够了超级详细内含源码!!!)

    目录 一 页面显示分页效果 1 1分析页面展示所要展示的属性有哪些 1 2分析页面有哪些每次发送请求有哪些公共的参数 二 具体实现前端通用分页 2 1分析思路 2 2具体实现的过程 2 2 1标签助手类 2 2 2创建标签库描述文件 tld
  • QTableView获取选中行指定列的内容(新手上路)

    1 第一次用QT写东西 在tableview对象后面的函数列表里翻来翻去 找了个看起来顺眼的selectedRows来试图获取选中行的内容 然后插入到list里面 QList
  • TQ2440移植u-boot2016.11全过程记录-【5】设置从NOR FLASH启动U-BOOT

    TQ2440移植u boot2016 11 设置从NOR FLASH启动u boot gedit include configs tq2440 h 屏蔽掉宏CONFIG SKIP LOWLEVEL INIT 修改宏CONFIG SYS TE
  • ModelArts平台部署模型

    相关步骤 构建镜像 上传镜像至swr服务 模型管理建立模型 部署模型上线 调用接口 1 构建自定义镜像 基于Dockfile文件构建 文件准备及文件结构 关于深度学习中的概念 训练 train 以图像识别为例 基于一个标注好的数据集训练好了
  • React-基础语法

    React 基础语法 React 搭建脚手架 安装node JS 安装React脚手架 创建项目 运行项目 其他命令 使用VSCode 安装插件 基础插件 文档目录结构 根组件App js 解析 组件解析 类组件 有状态组件 函数组件 JS
  • 软件测试项目案例哪里找?【银行/教育/商城/金融/等等....】

    项目一 ShopNC商城 项目概况 ShopNC商城是一个电子商务B2C电商平台系统 功能强大 安全便捷 适合企业及个人快速构建个性化网上商城 包含PC IOS客户端 Adroid客户端 微商城 系统PC 后台是基于ThinkPHP MVC
  • ### Paper about Event Detection

    Paper about Event Detection author gr date 2014 03 15 email forgerui gmail com 看一些相关的论文 1 Efficient Visual Event Detecti
  • 【动态规划】最少按多少下开关使灯全亮

    文章目录 无环条件下 题目描述 解题思路 递归版本 迭代版本 有环状态下 题目描述 解题思路 递归版本 迭代版本 无环条件下 题目描述 给定一个数组arr 长度为N arr中的值不是0就是1 arr i 表示第i栈灯的状态 0代表灭灯 1代
  • 介绍:教育研究:定量,定性和混合方法——伯克约翰逊,拉里克里斯滕森著

    www sagepub com bjohnson4e 章节资源的网站
  • 【图形学】GAMES101 Assignment3 作业框架分析

    GAMES101 Assignment3 作业框架分析 文章目录 GAMES101 Assignment3 作业框架分析 rasterizer draw rasterizer rasterize triangle 参考 写作业之前看了一眼代
  • java 多线程学习笔记之 线程互斥

    许多线程共享同一数据 这种情况在现实的生活中也是经常发生的 比如火车站的火车票售票系统 火车票售票系统是一个常年运行的系统 为了满足乘客的需求 我们不能只设一个窗口 必须设很多的售票窗口 每个售票窗口就像一个线程 它们各自运行 共同访问相同