多线程间通信

Qt 多进程和多线程的概念及进程间通信 进程可以简单的理解为一个可以独立运行的程序单位,它是线程的集合,进程就是有一个或多个线程构成的。而线程是进程中的实际运行单位,是操作系统进行运算调度的最小单位。可理解为线程是进程中的一个最小运行单元。那么多线程就很容易理解:多线程就是指一个进程中同时有多个线程正在执行。为什么要使用多线程? 阅读详情

多线程间通信

第一部分

1、线程通信

|--卖票和存钱,它们各自所要运行的代码都是一致的,如卖票程序,4个窗口分别卖票,4个窗口的程序都是相同的;
|--线程通信:现在有一堆资源,A线程在往里面存数据,B这个线程在往外面取数据,如同资源就是煤,有一个车在往里面拉煤,还有一个车在往外面送煤;这一进一出都是同时运行的;它们这两个动作是不一致的,所以它们的代码也就是不一致的;-->所以就要有两个run()方法来存放,那么就要有两个类来进行存放;
|--简单一句话:其实就是多个线程在操作同一个资源,但是操作的动作不同;

2、线程通信图形

3、代码体现

//描述类
class Res
{
//	定义两个变量
	String name;
	String sex;
	boolean flag =false;
}
//用实现的方法;
class Input implements Runnable
{
	private Res r;
	Input(Res r)
	{
		this.r = r;
	}
	public void run()
	{
//		做男和女的切换
		int x=0;
		while(true)
		{
//			synchronized(r)
//			{
//				if(r.flag)
//				try
//				{
//					r.wait();
//				}
//				catch (Exception e)
//				{
//					System.out.println(e.toString());
//				}
				if(x==0)
				{
					r.name ="mike";
					r.sex ="man";
				}
				else
				{
					r.name ="丽丽";
					r.sex ="女女女女女";
				
				}
//				切换
				x=(x+1)%2;
//				r.flag = true;
//				r.notify();
//			}
		}
	}
}
class Output implements Runnable
{
//	初始化资源
	private Res r;
	Output(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
//			synchronized(r)
//			{
//				if(!r.flag)
//				try
//				{
//					r.wait();
//				}
//				catch (Exception e)
//				{
//					System.out.println(e.toString());
//				}
				System.out.println(r.name+"....."+r.sex);
//				r.flag = false;
//					r.notify();
//			}
		}
	}
}
class InputOutputDemo 
{
	public static void main(String[] args) 
	{
//		创建资源
		Res r = new Res();
//		实现Runnable接口建立对象Input、Output
		Input in = new Input(r);
		Output out = new Output(r);
//		创建两个线程;
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
//		开启线程
		t1.start();
		t2.start();
	}
}
 

4、运行结果

从运行结果看,出现了相同的姓名,却有两个性别的产生,或者是相同的性别,出现了不同的姓名;

5、问题产生的原因

|--当Input往里面存mike和man的时候,这是丽丽也存进来了,但是这是刚存完丽丽,这时输出线程获取到了执行权,那么这时输出语句就把丽丽和man给打出去了;也就是说赋值的时候,只赋值了姓名,却没有赋值性别就被输出了;

6、解决问题

解决这个问题还要想到同步的两个前提;
|--是否是两个或者两个以上的线程;
|--是否使用的是同一个锁;

第二部分

1、线程通信等待唤醒机制

描述:输入的线程获取到了cpu的执行权,输入了一个mike和man,存完了以后,这是出了同步以后,那么Input和output就再次有可能会抢到cpu的执行权所以这是输入的input就把丽丽和女给输入进去了,前面的mike和man值给覆盖了;当Input获取到了执行权以后,就一直不断的录入,当路途到了某一个时候,它的执行权被输出的给强走了;输出获取到执行权之后,就有可能会把一个值打印多遍;所以造成了一大片的man和一大片的女;

2、问题的解决

在描述的资源上面加上一个标记;当Input在向资源里面存值的时候,要先判断一下,资源里面有没有值,如果标记是false的话,就往里面存入值,存完了以后,输入的还会持有执行权,这时存完后就应该把标记改为true,代表里面有数据了;这是应该让输入线程等待,输入线程应该是存完数据后,输出线程取完数据后,才能醒过来;所以要使用wait();-->也就是冻结了;这是输出语句就只有了cpu的执行权,判断标记为true,就取了一次数据,打印了以后,这是输出还有cpu的执行权就把标记改为了false;这时输出线程在等待之前要把输入线程给叫醒了,然后就等到了;以此类推-->线程通信中的等待唤醒机制。

3、代码体现

//描述类
class Res
{
//	定义两个变量
	String name;
	String sex;
//	定义一个标记
	boolean flag =false;
}
//用实现的方法;
class Input implements Runnable
{
	private Res r;
	Input(Res r)
	{
		this.r = r;
	}
	public void run()
	{
//		做男和女的切换
		int x=0;
		while(true)
		{
//			资源是唯一的
			synchronized(r)
			{
//				如果flag为true的话,就要等待,而放弃执行资格
				if(r.flag)//wait notify 和notifyAll全部用在同步里面;
//				wait方法要抛异常
				try
				{
					r.wait();//wait定义在Object里面,因为是任意对象可以调用的方法可以定义在上帝里面;
				}
				catch (Exception e)
				{
					System.out.println(e.toString());
				}
				if(x==0)
				{
					r.name ="mike";
					r.sex ="man";
				}
				else
				{
					r.name ="丽丽";
					r.sex ="女女女女女";
				
				}
//				切换
				x=(x+1)%2;
//				把flag改为true;
				r.flag = true;
//				叫醒输出线程,要使用锁,wait notify 和notifyAll全部用在同步里面;
				r.notify();
			}
		}
	}
}
class Output implements Runnable
{
//	初始化资源
	private Res r;
	Output(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
//			资源是唯一的
			synchronized(r)
			{
//				flag已经被置为了true,就是false,就不要等待,只要为true就要等待;
				if(!r.flag)
//				wait方法要抛异常
				try
				{
					r.wait();
				}
				catch (Exception e)
				{
					System.out.println(e.toString());
				}
				System.out.println(r.name+"....."+r.sex);
				r.flag = false;
//				唤醒输入线程
				r.notify();
			}
		}
	}
}
class InputOutputDemo 
{
	public static void main(String[] args) 
	{
//		创建资源
		Res r = new Res();
//		实现Runnable接口建立对象Input、Output
		Input in = new Input(r);
		Output out = new Output(r);
//		创建两个线程;
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
//		开启线程
		t1.start();
		t2.start();
	}
}
 

4、运行的结果

5、对代码进行优化;

/*
对代码继续优化;
*/
class Res
{
	private String name;
	private String sex;
	private boolean flag = false;
//	设置姓名和性别,在把函数同步
	public synchronized void set(String name,String sex)
	{
//		wait notify要放在锁里面;
//		非静态同步函数用的锁是this;
		if(flag)
			try
			{
				this.wait();
			}
			catch (Exception e)
			{
				System.out.println(e.toString());
			}
		this.name = name;
		this.sex = sex;
		flag = true;
//		非静态同步函数用的锁是this;
		this.notify();
	}
	public synchronized void out()
	{
		if(!flag)
			try
			{
				this.wait();
			}
			catch (Exception e)
			{
				System.out.println(e.toString());
			}
		System.out.println(name+"....."+sex);
		flag = false;
		this.notify();
	}
}
class Input implements Runnable
{
	private Res r;
	Input(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		int x=0;
		while(true)
		{
				if(x==0)
					r.set("mike","man");
				else
					r.set("丽丽","女女女女女女女女");
				x = (x+1)%2;
		}
	}
}
class Output implements Runnable
{
	private Res r;
	Output(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.out()	;		
		}
	}
}
class InputOutputDemo2 
{
	public static void main(String[] args) 
	{
//		创建资源;
		Res r = new Res();
//		创建线程;
		new Thread(new Input(r)).start();
		new Thread(new Output(r)).start();
	}
}

第三部分

1、生产者和消费者

|--需求想要对生产一个消费一个,并且都是带着标号的;

2、代码体现

class Resourse
{
//	产品名称
	private String name;
//	编号
	private int count =1;
//	设置标记
	private boolean flag = false;
//	同步函数
	public synchronized void set(String name)
	{
		if(flag)
			try
			{
				this.wait();
			}
			catch (Exception e)
			{
				System.out.println(e.toString());
			}
//			在设置名称的时候就带这编号往里面设置,就是你传一个张三,我传一个张三是带着编号的;
			this.name = name+"---"+count++;
//			告诉生产的是什么;
		System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
		this.flag = true;
		this.notifyAll();
	}
	public synchronized void out()
	{
		if(!flag)
			try
			{
				this.wait();
			} 
			catch (Exception e)
			{
				System.out.println(e.toString());
			}
		System.out.println(Thread.currentThread().getName()+"...消费者.................."+this.name);
		this.flag = false;
		this.notifyAll();
	}
}
class Producer implements Runnable
{
//	操作资源
	private Resourse res;
	Producer(Resourse res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			res.set("+++商品+++");
		}
	}
}
class Consumer implements Runnable
{
//	操作资源
	private Resourse res;
	Consumer(Resourse res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			res.out();
		}
	}
}
class  ProducerConsumerDemo
{
	public static void main(String[] args) 
	{
//		创建资源
		Resourse r = new Resourse();
		
		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);
//		创建线程;
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(pro);
		Thread t3 = new Thread(con);
		Thread t4 = new Thread(con);

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

3、运行结果

出现了一个现象就是,生产了两个而却消费了一个商品,或者是生产了一个,却消费了两个的现象;

4、问题的描述

|--现在出现了4个线程,两个是消费者,两个是生产者;假如现在消费者获取到了cpu的执行权,t1判断标记为false就不需要等待,向里面赋值了;就++了一次,并且将标记置为了true;但是这时又可能还持有执行权,这时的flag为true,判断标记是true,t1就等待了;t1就处于放弃资格,这时t2、t3和t4就有可能会抢到cpu的资源;t|--1(放弃资格)-->t2(放弃资格)-->t2(放弃资格)-->t1(获取资格)-->t3(放弃资格)-->t4(放弃资格)-->t1(获取资格)-->打印了一次

-->notify-->t2(获取资格)(这时t1把本方的唤醒了)-->t1(放弃资格)-->(t2不判断标记,又生产了一个)t2获取资格)-->t2没有判断标记,就导致生产了两个商品,但是消费的时候只消费了t2生产的商品;

|--主要原因就是在t2醒的时候没有判断标记,就向下生产了一个-->那么如何在每次醒的时候都要判断标记?-->用while进行多次的判断;

5、代码体现

class Resourse
{
//	产品名称
	private String name;
//	编号
	private int count =1;
//	设置标记
	private boolean flag = false;
//	同步函数
	public synchronized void set(String name)
	{
		while(flag)
			try
			{
				this.wait();
			}
			catch (Exception e)
			{
				System.out.println(e.toString());
			}
//			在设置名称的时候就带这编号往里面设置,就是你传一个张三,我传一个张三是带着编号的;
			this.name = name+"---"+count++;
//			告诉生产的是什么;
		System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
		this.flag = true;
//		全部唤醒所有的线程,它们自己会循环判断标记;
		this.notifyAll();
	}
	public synchronized void out()
	{
		while(!flag)
			try
			{
				this.wait();
			} 
			catch (Exception e)
			{
				System.out.println(e.toString());
			}
		System.out.println(Thread.currentThread().getName()+"...消费者.................."+this.name);
		this.flag = false;
//		全部唤醒所有的线程,它们自己会循环判断标记;
		this.notifyAll();
	}
}
class Producer implements Runnable
{
//	操作资源
	private Resourse res;
	Producer(Resourse res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			res.set("+++商品+++");
		}
	}
}
class Consumer implements Runnable
{
//	操作资源
	private Resourse res;
	Consumer(Resourse res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			res.out();
		}
	}
}
class  ProducerConsumerDemo
{
	public static void main(String[] args) 
	{
//		创建资源
		Resourse r = new Resourse();
		
		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);
//		创建线程;
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(pro);
		Thread t3 = new Thread(con);
		Thread t4 = new Thread(con);

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

6、运行结果

第四部分

1、1.5版本的新特性

import java.util.concurrent.locks.*;
class Resourse
{
	private String name;
	private int count =1;
	private boolean flag = false;
//	建立对象父类            子类
	private Lock lock = new ReentrantLock();
//	wait和nitifyAll都要所属于锁,但是wait和nitifyAll封装在Condition里面
//  所以Condition要通过Lock来,所以Lock里面有个Condition newCondition()方法;
	//两个Condition对象;
	private Condition condition_pro = lock.newCondition();//newContion是Lock中的方法。
	private Condition condition_con = lock.newCondition();//newContion是Lock中的方法。
//	没有synchronized同步了
//  没有catch到异常,就要抛出异常,标识一下
	public void set(String name)throws InterruptedException
	{
//		锁上,拿到锁
		lock.lock();//对象调用
		try//不要catch
		{
//			判断标记
			while(flag)
//				生产者等待
				condition_pro.await();//await要抛出异常
				this.name = name+"---"+count++;//这个放在等待的后面,
			System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
			flag = true;
//			唤醒对方的线程,这就是新特性出现的好处;
			condition_con.signal();//唤醒消费者者//这时就不要signalAll
		}
//		释放资源;
		finally
		{
			lock.unlock();//释放锁的动作一定要执行。//对象调用
		}
	}
	public void out()throws InterruptedException
	{
		lock.lock();//拿到锁
		try
		{
			while(!flag)
//				消费者等待
				condition_con.await();
			System.out.println(Thread.currentThread().getName()+"...消费者.................."+this.name);
			flag = false;
//			唤醒对方的线程,这就是新特性出现的好处;
			condition_pro.signal();//唤醒生产者,这时就不要signalAll
		}
		finally
		{
			lock.unlock();
		}
	}
}
class Producer implements Runnable
{
	private Resourse res;
	Producer(Resourse res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
//			这个调用了,也要抛出异常;
			try
			{
				res.set("+++商品+++");
			}
			catch (InterruptedException e)
			{
				System.out.println(e.toString());
			}
		}
	}
}
class Consumer implements Runnable
{
	private Resourse res;
	Consumer(Resourse res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				res.out();
			}
			catch (InterruptedException e)
			{
				System.out.println(e.toString());
			}
		}
	}
}
class  ProducerConsumerDemo2
{
	public static void main(String[] args) 
	{
		Resourse r = new Resourse();
		
		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);

		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(pro);
		Thread t3 = new Thread(con);
		Thread t4 = new Thread(con);

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

	}
}
 

生产者唤醒消费者,消费者唤醒生产者;

在该例中实现了本方只唤醒对方操作;

2、运行结果

3、面试

问:生产者和消费者有什么替代方案?
答:1.5版本以后提供了现实的锁机制,以及现实锁对象上的等待唤醒操作机制,同时把等待唤醒进行了封装,这样一个锁可以对应多个condition ;

5、我的总结

|--wait notify 和notifyAll全部用在同步里面,因为要对持有的监视器(锁)进行操作;
|--wait notify 和notifyAll定义在Object里面,因为是任意对象可以调用的方法可以定义在上帝里面;
|--在线程里面的唤醒机制,如果唤醒的话,是唤醒的第一个等待的线程;按照顺序进行唤醒的;
|--notify 往往唤醒的是线程池中的第一个;
|--当多个生产者和消费者同时在做事情的事情,必须要写while循环-->循环判断标记,必须要用notifyAll-->唤醒所有的线程;
|--1.5版本的新特性
|--Lock 替代了 synchronized 方法和语句的使用,
|--Condition 替代了 Object 监视器方法的使用。wait notify 和notifyAll被Condition 所取代;
|--await替代了wait 
|--singal替代了notify 
|--notifyAll替代了notifyAll

|--JDK 提供的新方案,这样一个锁可以对应多个condition 

|--lock

|--condition_pro

|--condition_con

|--释放锁的动作一定要执行;
29、多线程同步与进程间通信技术解析 本文深入解析了多线程同步与进程间通信(IPC)的核心技术,包括多线程编程中的同步要点、线程管理复杂性以及相关的拓展技术如.NET类和MSMQ服务。详细介绍了匿名管道和命名管道的使用场景及实现方法,并提供了命名管道客户端与服务器端的代码示例。文章还探讨了多线程与进程通信的综合应用,总结了开发中的最佳实践与未来技术趋势。 阅读详情

相关推荐

38、多线程与进程间通信:管道的使用与实现

本文介绍了多线程编程和进程间通信中的管道机制,包括多线程的创建与控制、管道的基本概念及实现方式,以及命名管道和客户端/服务器模型的应用。通过示例代码详细讲解了popen、pipe等函数的使用方法,并总结了多线程与管道结合的实际应用场景及注意事项。

jj890的博客 57

实验八 进程间通信+多线程

一、实验目的 1、了解采用进程间通信的原理; 2、掌握线程的创建及使用方法,学习进行多线程编程。 二、实验内容 (1)在Linux系统下编写完成。 (2)创建一个服务器和若干个客户端。 (3)用户可以实现包括:通过客户端输入文字并且向服务器发送消息,也可以接收来自服务器端的数据。用户控制客户端退出。 (4)服务器端可以实现包括:接收并区分来自客户端的数据,将用户输入的内容在服务器上打...

diOSyu的博客 2410

多线程编程与进程间通信的实践与思考

本文探讨了多线程编程中的线程创建和管理,以及进程和线程之间的通信和同步问题。通过实际代码示例和详细解释,揭示了线程属性的设置和线程间依赖关系的重要性。同时,文章强调了标准cout的线程不安全性,并对未来章节中进程和线程通信模型的深入探讨进行了展望。

weixin_42234168的博客 473

C++ 多进程多线程间通信

在这个示例中,我们创建了一个全局的std::queue<int>作为消息队列,以及一个互斥锁std::mutex和一个条件变量std::condition_variable来同步对消息队列的访问。管道提供了一种半双工的通信方式,一个线程往管道中写入数据,另一个线程从管道中读取数据。信号的接收:当信号被发送到进程时,操作系统会中断该进程的正常流程,并调用相应的信号处理函数(如果已设置)。请注意,这里的互斥锁是在全局命名空间中创建的(通过前缀"Global\\"),这意味着它可以在系统范围内的任何进程中访问。

zxf347085420的博客 1268

Acute逻辑分析仪TL4134E实战:从触发电平到协议解析的完整避坑指南

本文是一份针对Acute逻辑分析仪TL4134E的实战避坑指南。文章深入解析了触发电平分组、采样率与存储深度权衡、高级触发等核心概念,并提供了混合电压系统测量、eMMC调试内存优化、SPI/I2C/UART协议解析排错等具体配置技巧,帮助硬件工程师和嵌入式开发者高效捕获与分析数字信号,快速定位通信问题。

weixin_29207149的博客 407

Linux-BSP-WIFI驱动移植与调试实战——以RTL8189FS为例

本文以RTL8189FS为例,详细介绍了Linux BSP中WiFi驱动移植与调试的全流程。涵盖硬件原理图分析、内核配置、设备树适配、驱动编译加载及问题排查等关键步骤,提供实用的调试技巧和解决方案,帮助开发者高效完成嵌入式WiFi驱动开发。

moon9的博客 399

JAVA多线程基础 之六 多线程间通信

wait与notify 使用wait和notify方法实现线程间的通信(属于Object的方法) 必须配合synchronized关键字使用。 wait方法释放锁,notify方法不释放锁。 public class WaitNotifyTest {// 在多线程间共享的对象上使用wait private String[] shareObj = { "true" }; ...

haponchang的博客 331

Halcon频域滤波实战:5分钟搞定傅里叶变换与功率谱分析(附完整代码)

本文提供Halcon频域滤波的实战指南,重点讲解如何利用傅里叶变换与功率谱分析快速解决图像处理难题。通过核心算子fft_image和power_real,演示了从空间域转换到频域、分析功率谱以定位周期性噪声,并构造滤波器进行精准去除的完整流程,附有可直接运行的代码示例。

docker8compose的博客 216

使用 异步多线程TCP Socket 实现进程间通信

使用 异步多线程TCP Socket 实现进程间通信(VC 6.0 , BCB6.0调试通过)              进程间通信有很多种方式,比如说 Pipe,共享内存,DDE,Socket等,关于进程通信方面的知识我在这里就不讨论了,大家可以看我博客里的另一些文章有讲...今天我们主要讨论怎么样使用Socket实现进程间通信。          本程序将使用Socket 的

jfkidear的专栏 2425

Windows与Linux安装miniconda并启动python项目及指令

官方介绍:Miniconda 是 conda 的免费最小安装程序。它是 Anaconda 的一个小型引导版本,仅​​包含 conda、Python、它们都依赖的包以及少量其他有用的包(例如 pip、zlib 等)。如果您需要更多软件包,请使用该 命令从 Anaconda 公共存储库或其他渠道(例如 conda-forge 或 bioconda)默认提供的数千个软件包中进行安装。minicoda下载地址最好挂个梯子。如果你需要指定版本的conda,可以在这里下载历史版本的miniconda。

一直走的很慢的鸭子 3194

手把手教你用LaTeX完成Elsevier期刊投稿:附完整文件上传清单与注意事项

本文提供了一份详尽的Elsevier期刊LaTeX投稿实战指南。文章系统拆解了从稿件准备、文件上传到最终提交的全流程,重点解析了Manuscript、Figure(s)等关键文件的上传逻辑与注意事项,并附有PDF生成前后的详细检查清单,旨在帮助研究者高效、规范地完成投稿,规避常见错误。

weixin_29300931的博客 490

Java 多线程 - 2 - 进程间通信方式

进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。IPC 对象的持续性分为三种:随进程,随内核和随文件系统。

老高的IT职场专栏 1524

会计引擎:交易与核算分离的前世今生

一、为什么需要会计引擎 金融产品的设计,一如一块硬币需要兼顾两面:一面是为客户提供好的金融服务,满足客户支付结算、借贷、资产保值增值等方面的需求,并在这个过程中,以数字化的方式做好客户资产的登记,登记的载体,则是“分户”或“台账”,如客户存款户,是一种典型的分户--资金的增减变化都在一个账户中进行体现,而客户购买的银行理财,因为收益率、期限、投资标的不同,每一笔持有就形成一行记录,即为“台账”--这当然是不严谨但相对形象的表述。但是,“分户”和“台账”并没有必然的区别,以贷款为例,一些银行仍然存在所谓“

银行信息系统应用架构详解 986

linux pipe 多线程_【Linux系统】Linux进程间通信

作者:Vamei出处:http://www.cnblogs.com/vamei我们在Linux信号基础中已经说明,信号可以看作一种粗糙的进程间通信(IPC, interprocess communication)的方式,用以向进程封闭的内存空间传递信息。为了让进程间传递更多的信息量,我们需要其他的进程间通信方式。这些进程间通信方式可以分为两种:管道机制:可以使用管道将一个进程的输出和另一...

weixin_31523181的博客 238

零基础做完YOLOv8船只检测系统:HRSC2016数据集 + 完整UI,稳过答辩

亲爱的同学,通过这篇教程,你已经掌握了“基于YOLOv8的HRSC2016微小船只检测系统”从数据集处理、模型训练到Tkinter界面开发的全流程。这个课题既贴合“海事智能化”的产业战略,又涵盖了“目标检测、深度学习、界面开发”等多个毕设评分点,非常适合作为计算机或海事工程专业的毕业设计。在实践中,你可能会遇到“海面背景复杂导致船只漏检”“微小船只识别精度不足”“UI与模型推理同步卡顿”等挑战——别担心,这些都是技术成长的必经之路。

FJN110的博客 110

聊聊蓝牙配对技术-CTKD OVER BR/EDR

摘要:本文探讨了蓝牙设备通过跨传输密钥派生(CTKD)机制实现双模连接的技术细节。研究发现,手机在连接双模耳机时优先通过BR/EDR配对,再利用CTKD派生BLE连接所需的密钥。关键条件包括:设备地址一致性、启用安全连接(Secure Connection)及禁用justworks配对方式。文章详细剖析了从BR/EDR链路密钥派生BLE长期密钥(LTK)的算法流程,重点解析了H6/H7加密函数的作用机制与安全差异。研究还通过HCI日志验证了密钥交换和加密建立的完整过程,指出蓝牙5.1版本对CTKD安全性的强

十多年蓝牙协议软件开发,擅长蓝牙协议分析 2703

Linux多线程间通信和多进程间通信的方式

进程间通信的概念 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication) 进程间通信的7种方式 第一类:传统的Unix通信机制 管道/匿名管道(pipe) 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道。 只能用于父子进程或者兄

landishu的专栏 1万+

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

python学习笔记(进程间通信、多进程和多线程总结)

进程间通信之生产者消费者模型

mkgdjing的博客 2654

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

linux系统多线程间通信和多核多线程场景下volatile的使用误区

然而,在C语言中(没有std::atomic),我们通常使用volatile来防止编译器优化,同时使用内存屏障来保证多核可见性(例如在Linux内核中,使用volatile和barrier()宏)。同步机制方面,互斥锁(mutex)是最基础的,用于保护临界区资源。内存可见性(多核/多线程):由于现代处理器的缓存一致性机制,一个CPU核心的写操作可能不会立即被另一个核心看到(尽管在单核系统中中断处理程序与主程序在同一个核心上运行,但中断会打断主程序,所以缓存是一致的,不需要额外屏障,但多核系统中则不同)。

shq8580的博客 1770

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

多线程间通信的问题

一 多线程间通信的问题多线程间通信的问题 本质上就是, 一个线程负责维护一个变量/结构体, 另外的一个(多个)线程读取这个变量结构体的内容eg: 线程A维护结构体struA, 线程B需要不断的读取struA的内容多线程间通信时, 编码面临最大的问题在于 读取的信息不一致, 读脏数

6943

进程线程 多线程间通信

采用全局变量,一个进程中的多个线程独享栈空间而进程的文本段、数据段、堆区是多线程共享的,又由于全局变量在数据区,故可以采用全局变量的方式进行多线程通信。

2303_78816874的博客 393

多线程间通信---监视线程

多线程间通信---监视线程:  一、多线程间通信---监视线程:  用自己的话来说,就是线程间的通信,一个线程执行,同时用另一个线程来监视目标线程的运行状态.    二、以统计文件为例:   1.统计文件的线程类: package 监控线程; import java.io.File; /** * 统计某一个磁盘的相关文件数据 * @author Administ...

凉皮,肉夹馍 286
上一篇: 多线程(死锁)
下一篇: Java-集合框架
fyldragonfyl
博客等级 码龄12年 9粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值