线程同步问题

使用 Linux 系统提供的线程同步 API 解决线程同步问题 一、用信号量完成四个线程的同步。主程序创建四个线程,其中两个线程负责 从文件读取数据到公共缓冲区,另两个线程从缓冲区读取数据分别做加、乘运算。 运行程序之前先编辑好数据文件 file1.dat 和 file2.dat,分别输入 1 2 3 4 5 6 7 8 9 10 和-1 -2 -3 -4 -5 -6 -7 -8 -9 -10。 阅读详情

在此之前我先给出这样一个情景:
锅里有一个饼,有两个饥饿的人同时看到了这个饼,按理来说,只有一个人能够吃到饼,那如果我们把饼看作一个信息,饥饿的人看作两个线程,会发生什么?

package com.Test;

public class Cookies_and_hugry_people extends Thread {
	
	int cookies_num = 1;//表示一块饼
	public void run() {
		
		System.out.println(Thread.currentThread().getName()+"来了");
		
			System.out.println("桌上有" + cookies_num + "块饼");
			if(cookies_num != 0) {
				System.out.println(Thread.currentThread().getName()+"想吃饼");
				cookies_num--;
				System.out.println(Thread.currentThread().getName() + "吃掉一块饼,还剩" + cookies_num + "块饼");

			}
			
		
	}

	public static void main(String[] args) {
		Cookies_and_hugry_people obj = new Cookies_and_hugry_people();
		new Thread(obj,"小明").start();
		new Thread(obj,"小刚").start();
	}
}

结果输出为这样
在这里插入图片描述
还剩-1块饼?!
显然,两个线程共用了桌上有1块饼的信息最后竟然无中生有暗度陈仓,这显然不是我们希望看到的结果。所以我们可以想办法让一个线程进行完以后再让另一个线程去执行代码

只需要给代码块加上锁就好了

public void run() {

		System.out.println(Thread.currentThread().getName() + "来了");
		synchronized (this) {//新加代码,给该部分上锁

			System.out.println("桌上有" + cookies_num + "块饼");
			if (cookies_num != 0) {
				System.out.println(Thread.currentThread().getName() + "想吃饼");
				cookies_num--;
				System.out.println(Thread.currentThread().getName() + "吃掉一块饼,还剩" + cookies_num + "块饼");

			}
		}

	}

其运行结果为
在这里插入图片描述

synchronized 字面意思为同步,其后面的括号里为一个对象,即对括号中的对象上锁,在一个线程中,这个对象进入代码块就相当于上了锁,必须等其运行完整个代码后才解锁,让另一个线程对象进来。

生产者消费者模式
先在我们再次假设一个情景,有一个生产饼干的机器,能够源源不断地生产出饼干来,放到桌上,并且能够判断桌上是不是放满了饼,如果桌上放不下了,机器就会停止生产(生产者);然后有饥饿的人,只要桌上有饼就会吃掉饼(消费者)。

package com.Test_producer_and_consumer;

import java.util.ArrayList;

public class Producers extends Thread{
	ArrayList<String> cookies=new ArrayList<>();
	public Producers(ArrayList<String> cookies) {
		this.cookies=cookies;
	}
	public void run() {
		System.out.println("机器准备就绪~~~");
		while(true) {
			
				try {
					synchronized (cookies) {
					Thread.sleep(1000);

					if(cookies.size()<3) {
						cookies.add("饼"+cookies.size());
						System.out.println("机器生产了一个饼,现在有"+cookies.size()+"个饼");
						cookies.notify();
					}
					if(cookies.size()==3) {
						System.out.println("桌上装不下饼了,机器停止生产");
						cookies.wait();
					}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

将饼装在**ArrayList**队列里面。互斥对象为cookies,当桌上装满了饼则会呼叫饥饿的小明过来吃饼

package com.Test_producer_and_consumer;

import java.util.ArrayList;

public class Resumer extends Thread{
	ArrayList<String> cookies =new ArrayList<>();
	public Resumer(ArrayList<String> cookies) {
		this.cookies=cookies;
	}
	public void run () {
		System.out.println("饥饿的小明准备就绪~~~~");
		while(true) {
			synchronized (cookies) {
				try {
					Thread.sleep(1000);
					if(cookies.size()>0) {
						cookies.remove(0);
						System.out.println("小明吃掉了一个饼,现在有"+cookies.size()+"个饼,又可以叫机器做饼了,呼叫机器");
						
						cookies.notify();
					}
					if(cookies.size()==0) {
						System.out.println("桌上的饼吃光了,小明停止吃饼");
						cookies.wait();
					}
					
					
					
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}

然后将两个线程同时启动

package com.Test_producer_and_consumer;

import java.util.ArrayList;

public class Main {
	public static void main(String[] args) {
		ArrayList<String> cookies=new ArrayList<>();
		new Producers(cookies).start();
		new Resumer(cookies).start();
	}
}

运行结果如下
在这里插入图片描述
我们可以看到,小明吃了饼以后需要开始呼叫机器,但由于此时程序并没有结束小明不会停止吃饼只有等到饼吃完以后,小明停止吃饼了,机器才能进入自己的代码块,也就是说关于cookies对象的代码块被锁住了
如果我们在生产一个饼之后机器就停下来就会出现这样的情况:

package com.Test_producer_and_consumer;

import java.util.ArrayList;

public class Producers extends Thread{
	ArrayList<String> cookies=new ArrayList<>();
	public Producers(ArrayList<String> cookies) {
		this.cookies=cookies;
	}
	public void run() {
		System.out.println("机器准备就绪~~~");
		while(true) {
			
				try {
					synchronized (cookies) {
					Thread.sleep(1000);

					if(cookies.size()<3) {
						cookies.add("饼"+cookies.size());
						System.out.println("机器生产了一个饼,现在有"+cookies.size()+"个饼");
						cookies.notify();
						cookies.wait();
					}
					if(cookies.size()==3) {
						System.out.println("桌上装不下饼了,机器停止生产");
//						cookies.wait();
					}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

对比之前的Producers类,机器在生产一个饼之后就开始wait了。
在这里插入图片描述

Java中多线程同步问题的解决方法 Java中的多线程同步问题是一个复杂的问题,但通过使用上述的多种方法,可以有效地解决这些问题。在实际开发中,应根据具体的需求和场景选择合适的同步方法。例如,对于简单的同步需求,可以使用关键字;对于需要更灵活锁机制的场景,可以使用;对于需要控制线程访问资源数量的场景,可以使用Semaphore等。同时,还应注意避免过度同步,以免影响程序的性能。希望本文的内容能够帮助读者更好地理解和解决Java多线程同步问题。 阅读详情

相关推荐

手把手教你用DCA1000EVM解析IWR6843毫米波雷达数据(附MATLAB代码)

本文提供了一份详尽的实战指南,手把手教你使用DCA1000EVM采集并解析TI毫米波雷达IWR6843的原始数据。内容涵盖硬件连接配置、mmWave Studio参数设置、LVDS数据流结构解析,并附有核心MATLAB代码,详细演示了从原始二进制文件到距离-速度谱的信号处理全链路,帮助开发者快速掌握数据解析与处理的关键步骤。

terraform7cloud的博客 228

线程同步的经典问题

当哲学家 1 和哲学家 2 抢到各自左手边的筷子后,同时需要右手边的筷子,但此时右手边的筷子已被哲学家 2 和哲学家 3 已经拿起,等待哲学家 2 和哲学家 3 放下右边筷子后,哲学家 1 和哲学家 2 才能拿到右手边的筷子,才能进餐。线程同步还可以提高程序的执行效率,对于频繁访问共享资源的应用,如果没有线程同步机制,可能会出现一些性能问题,例如资源等待、线程竞争等等。总之,生产者消费者问题是一个经典的线程同步问题。此时,让哲学家先使用右边的筷子,再使用左边的筷子,吃完面条之后,把这两个筷子放回原处。

weixin_46326585的博客 922

python 编程 安卓脚本_详解基于Android的Appium+Python自动化脚本编写

1.AppiumAppium是一个开源测试自动化框架,可用于原生,混合和移动Web应用程序测试, 它使用WebDriver协议驱动iOS,Android和Windows应用程序。通过Appium,我们可以模拟点击和屏幕的滑动,可以获取元素的id和classname,还可以根据操作生成相关的脚本代码。下面开始Appium的配置。appPackage和APPActivity的获取任意下载一个app解压...

weixin_39523625的博客 2930

线程同步(一)

线程同步的概念及线程同步方式

好好学习,天天向上 2801

SAP(ERP)工艺路线(Routing)业务视角解析

工艺路线(Routing)也是PP模块,即生产制造模块中最重要核心主数据之一,也是ERP(SAP)顾问,必需从业务与系统深入掌握的重要主数据,它也是整个生产计划与生产流程的重要基础。因为执行步骤只是操作层面的认知,业务顾问需要从业务本质上去理解它,要真正从业务视角理解工艺路线的业务价值,而不仅仅是操作层面的认知。因此将工艺路线理解为“有以上业务本质的理解,然后进到SAP系统中,就容易理解工艺路线(Routing)的每一组成部分结构与功能了,本质就是理解制造企业如何将设计意图转化为物理现实的编码规则。

m0_45197968的博客 1503

pip install mysql出现error: subprocess - exited-with-error的解决方案

本文主要介绍了pip install mysql出现error: subprocess - exited-with-error的解决方案,希望能对使用mysql的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 5万+

线程中的同步机制问题(三种解决方法)

线程的同步机制(三种解决方法),synchronized中的同步代码块、同步方法以及lock锁机制。

咸鱼老潘的编码生活 1935

12、每日卫星任务规划问题的不同公式

本文探讨了卫星任务规划问题的多种数学公式表示方法,包括传统的整数线性规划(ILP)模型、改进的基于路径的公式、基于集合覆盖的公式以及动态规划公式。通过案例研究比较了不同公式的求解效率和适用场景,并提供了使用Python进行实际求解的操作步骤。最后讨论了进一步优化策略及未来研究方向,旨在为解决卫星任务规划问题提供全面的理论支持和实践指导。

assembly8low的博客 204

【Java学习】多线程-线程同步方案&线程池

线程同步就是让多个线程实现先后依次访问共享资源,这样就解决了安全问题,它最常见的方案就是加锁加锁:每次只允许一个线程加锁,加锁后才能进入访问,访问完毕后自动解锁,然后其他线程才能再加锁进来线程池就是一个可以复用线程的技术它就像一个大的池子一样,里面可以放置一些线程,当需要的时候,就从里面取出来用,用完了就还回去如此一来,就不必频繁的创建和销毁线程了,大大的提高了线程的利用率,提供系统的性能1、任务进入线程池,先看核心线程是否满了,如果没满则创建新的核心线程。

weixin_69134024的博客 1408

Python-增加b站视频播放量

如果条件允许的情况下,有代理API更好,每次请求url调用API也更方便。如果没有的话,也不用担心,网上本身也有着很多免费国内代理,不过代理是否可用需要自己花点时间去检测,检测方法笔者这里就不详述了,后面有时间的话会单独针对这一块做详细说明。在开始之前,需准备代理IP。总之,在每次请求url的时候,随机带入某个IP防止被平台检测,便于达到增加播放量预期。大致思路就是针对你的目标代理平台进行IP抓取,并存入到自己本地的IP代理池。本文是该专栏的第1篇,后面会持续更新对应平台干货知识,记得关注。

Python进阶专栏《爬虫实战进阶》,《Pyppeteer从入门到精通》原创作者 5214

31、车载通信中的可见光通信(VLC)技术解析

本文详细解析了车载通信中可见光通信(VLC)技术的应用背景、优势及发展前景。对比传统RF通信技术(如DSRC),VLC利用LED照明设备实现高效、安全的车辆与车辆、车辆与基础设施之间的通信,具有频谱资源丰富、安全性高、无电磁干扰等优势。文章还探讨了VLC在交叉口交通控制、高速公路通信、自动驾驶等场景的应用潜力,展望了其在未来智能交通系统中的重要作用。

hill8的博客 318

Java并发编程精讲

课程会讲解Java中并发相关技术的基础、原理和应用,从线程安全、线程(池),锁实现和并发容器等高并发Java实现,去深入理解在并发编程中,一些最容易被忽视的点,这些点也是我在多年编程经验中实际用到,对于每个小节小课均会有实际的场景应用为你呈现。同时这些也是面试过程中面试官考察的重点,掌握这些点,面试和工作时,做到心中有货,不慌不乱,能够胜任。

Python - 多页pdf 合称为一页

尝试使用 ReportLab 来重画 pdf,但探索起来有点麻烦。重要的是解决手头这个问题,所以就算方法蠢,但简单完事。以下生成结果,最有一页 pdf 可能会显示在第一页,手动编辑下 pdf 即可;或者你也可以修改代码逻辑来完善。打印ppt,一页占用A4纸比较浪费,想多页合成一个 A4大小;安装 fitz,单独安装 fitz 使用可能会报错。将 PDF 拆分为 图片来保存。

AI工程化、开源分享、文档翻译、代码笔记 1425

线程安全,线程同步,解决线程同步问题

线程安全,线程同步,解决线程同步问题,synchronized,同步代码块,同步方法

weixin_46140377的博客 884

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java多线程 - 线程安全和线程同步解决线程安全问题

线程安全问题。

dzqxwzoe的博客 978

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

深入解析线程同步中WaitForSingleObject的超时问题

线程同步要考虑操作系统调度特性WaitForSingleObject的参数是"最大等待"而非"检测间隔"完善的错误恢复机制至关重要动态调整等待时间可以提高系统健壮性希望这篇分析能帮助遇到类似问题的开发者。良好的线程同步设计就像交通信号灯,需要合理的"等待时间"设置才能保证系统流畅运行。

码事漫谈 1291

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

二、多线程同步问题

一、线程安全问题 比如同一个账户,加入父亲和儿子同时在不同的窗口同时取钱,比如剩余1000块,父亲取了800,儿子也取了800,不同窗口没有及时同步数据,可能就会实际支出了1600,而这是不允许发生的; - 这种不安全的问题并不是一定会发生,取决于线程的具体调度; - 但是一旦发生,就是灾难性的,必须在代码层面解决; 账户类 public class Account { private double balance; private String name; // set及get及有

weixin_43374578的博客 3484

[java多线程]的同步问题

指的是多个线程同时修改一个过程时,可能导致的问题 引入: 以卖票问题为例:假设总共有十张票,三个黄牛卖票(代表三个子线程),预测最后一个黄牛卖完票,还剩下0张票 package se.SE.practice; class MyThread implements Runnable { private int ticket=10; @Override public vo...

weixin_42645168的博客 234

线程同步问题的引出

假设现在有一个卖票的情景,票数是固定的,正常情况下每当一个人买完n张票,票数就减少n张,然后直到票数为0为止。下面我们简单的模拟该情景: class TickectThread implements Runnable{ private int tickect = 5; @Override public void run() { for(int i = 0; i < 1...

写写代码 203

Java的线程同步和并发问题示例

并发问题 多线程是一个非常强大的工具,它使我们能够更好地利用系统的资源,但我们需要在读取和写入多个线程共享的数据时特别小心。 当多个线程尝试同时读取和写入共享数据时,会出现两种类型的问题 - 线程干扰错误内存一致性错误让我们逐一理解这些问题。 线程干扰错误(竞争条件) 考虑以下Cou...

cheyun0833的博客 396

线程安全问题 线程同步

线程安全问题,同步1.线程安全问题1.1.什么是线程安全1.2.问题演示1.2.1.第一步:创建售票线程类1.2.2.第二步:创建测试类1.3.问题分析1.4.问题解决-线程同步1.4.1.同步代码块(synchronized)1.4.2.同步方法(synchronized)1.4.3.同步锁(ReenreantLock)标题1.5.小结 哔哩哔哩大神的视频整理 1.线程安全问题 1.1.什么是线程安全 如果有多个线程同时运行同一个实现了Runnable接口的类,程序每次运行结果和单线程运行的结果是一样的,

weixin_45229007的博客 404

java Android 中关于线程同步问题

Java 两个线程间的通信

u012288123的专栏 3059
上一篇: 线程起步,解决一个过程只能进行一次画图的问题
下一篇: 彻底解决java传参问题
南懿烨曦
博客等级 码龄6年 108粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值