多线程第七篇:互斥和同步总结

2024-08-24 16:18

本文主要是介绍多线程第七篇:互斥和同步总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   同步:多个线程(进程)之间有严格的先后顺序,一个线程(进程)的执行,依赖于另一个.
   互斥:多个线程(进程)没有先后顺序,谁抢到算谁的.
 

注意:线程的创建和执行是分开的,并不是创建后立即执行,而是创建后,等待cpu调度.

window中的四种线程(进程)间同步与互斥.
criticalSection,mutex,event,semaphore

criticalSection:
     1.中文名称临界区或者关键段,用于线程间互斥.
     2.进入和离开必须成对出现.
     3.不是内核对象,不能用于进程间互斥,只能用于线程间互斥
     4.由于不是内核级对象,所以速度较快,效率较高.
使用:
     1.InitializeCriticalSection
     2.EnterCriticalSection
     3.LeaveCriticalSection
注意事项:
     临界区为子线程所有,主线程中使用临界区并不能实现互斥.


mutex:
     1.互斥区,用于线程(进程)间互斥
     2.记录拥有着,可以处理遗弃问题,当前使用该互斥区的线程(进程)占有该互斥区,并且,其他线程(进程)不能使用.
     3.可以在线程A中waitforsignalobject,在线程B中release.
     4.是内核对象,可以进行进程间互斥.
使用:
     1.CreateMutex或者OpenMutex
     2.ReleaseMutex 
     3.WaitForSingleObject
     4.CloseHandle
event:
     1.事件,用于线程(进程)间同步和互斥.
     2.是内核对象,不具有拥有权,即可以由一个线程(进程)触发,而由另一个线程(进程)恢复.
使用:
     1.CreateEvent
     2.SetEvent
     3.ResetEvent
     4.PulseEvent
     5.WaitForSingleObject
     6.CloseHandle

semaphore:
     1.信号量,用于线程(进程)间同步和互斥.
     2.是内核对象,不具有拥有权,可以在不同的线程(进程)中进行PV操作.
使用:
     1.CreateSemaphore 或OpenSemaphore
     2.ReleaseSemaphore(+n)
     3.WaitForSingleObject(-1)
     4.CloseHandle

遗弃问题:
     由于临界区是线程级别使用的,线程的操作都是由主线程控制的,当一个正在使用临界区的线程突然崩溃会怎么样呢?由于临界区会记录使用的线程,所以同样可以处理遗弃问题.

遗弃问题:
     由于进程(线程)突然死亡,而没有进行任何善后处理,这样会造成资源永远被占用,需要一种方法来解决.
 
解决之道
     当mutex使用者突然死了,那么mutex归零,等待其他使用者占有然后使用.
为什么event和semaphore不可以:
     因为event和semaphore并不记录其使用者,他的使用者死了event和semaphore并不知道,他只知道自己被使用,等待被释放.
     如果event和semaphore的使用者突然死亡,而其进程都在等待event和semaphore可用,那么这就造成了死锁.


为什么mutex和临界区(critical_section)不能进行同步:
   因为mutex和critical不能再主线程中使用,而信号量和事件都可以在主线程中使用.
   回忆一下,我们每次进行线程间同步的时候,总是先在主线程先设置事件或者信号量的状态,然后再在线程中设置,这样线程就可以使得线程有先后顺序了,即实现同步.核心在于主线程总是第一个执行,然后再执行子线程,这样就可以有先后顺序,如果不在主线程中设置,只是让子线程进行同步,也可以这需要一个全局变量,来进行检测是不是该这个线程执行.

我们用临界区+全局变量来实现一个线程同步:
#include <iostream>
#include <windows.h>
#include <process.h>
int g_count = 0;
CRITICAL_SECTION all;
unsigned int __stdcall producer (void *)
{
int ID = 0;
bool flage = true ;
while ( flage   ){
EnterCriticalSection (&all );
if ( g_count == ID ){
std ::cout << "producer"<< std ::endl ;
flage = false ;
g_count ++;
}
LeaveCriticalSection (&all );
}
return 0;
}
unsigned int __stdcall consumer (void *)
{
int ID = 1;
bool flage = true ;
while ( flage   ){
EnterCriticalSection (&all );
if ( g_count == ID ){
std ::cout << "consumer"<< std ::endl ;
flage = false ;
}
LeaveCriticalSection (&all );
}
return 0;
}
int main ()
{
InitializeCriticalSection(& all );
HANDLE hproducer = (HANDLE ) _beginthreadex( NULL ,0,producer , NULL,0, NULL );
HANDLE hconsumer = (HANDLE ) _beginthreadex( NULL ,0,consumer , NULL,0, NULL );
WaitForSingleObject( hproducer ,INFINITE );
WaitForSingleObject( hconsumer ,INFINITE );
return 0;
}

扩展:
      可不可以让信号量和事件实现遗弃呢? 
      当然可以,我们可以在线程调用信号量或事件的时候,在内核对象中添加该进程号.在进程表或其他地方注册一个回调函数,此函数功能是当该进程或线程崩溃的时候,通知相关内核对象(信号量内核对象或者事件内核内核对象),此线程已崩溃,删除该线程相关信息.
     此机制类似于epoll机制,有兴趣可以了解一下.


这篇关于多线程第七篇:互斥和同步总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1102972

相关文章

RabbitMQ消费端单线程与多线程案例讲解

《RabbitMQ消费端单线程与多线程案例讲解》文章解析RabbitMQ消费端单线程与多线程处理机制,说明concurrency控制消费者数量,max-concurrency控制最大线程数,prefe... 目录 一、基础概念详细解释:举个例子:✅ 单消费者 + 单线程消费❌ 单消费者 + 多线程消费❌ 多

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Linux实现线程同步的多种方式汇总

《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意