热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

新手学C++多线程编程(6)合作与同步

C多线程编程(6)合作与同步转载▼C多线程编程(6)合作与同步1.数据竞争(datarace)竞争条件(racecondition):当两个或更多线程或进程试图同时修改同一个共享、

C++多线程编程(6)合作与同步

 
转载




C++多线程编程(6)

合作与同步

 

1.数据竞争(data race)/竞争条件(race condition):当两个或更多线程或进程试图同时修改同一个共享、可修改数据块时。为了让竞争条件存在,目标内存块必须是可修改的,而且线程必须试图同时访问这个块,至少其中一个线程试图修改这个内存块。

创建竞争条件是多线程或并发编程的主要缺陷之一,另一个缺陷就是死锁。

 

2.死锁:每个线程轮流排他性访问变量或对象,以解释线程之间可能的竞争条件,可以提供一种lock()机制来实现。lock()机制使锁定的变量只能被首先调用lock()机制的线程访问,即一个线程A先锁定资源(变量或对象等),另一个线程B就无法锁定该资源,此时线程A和线程B互相等待对方释放资源,这种情况称作死锁(deadlock)。当锁定、挂起或冻结多个线程时,相互间等待对方释放资源,此时存在死锁。

解决途径:多个线程和多个任务同步与合作使用资源。

 

3.同步:允许多个线程或进程同时激活,同时共享资源而不干扰对方的操作。同步进程临时序列化多个程和任务的执行,防止竞争条件或死锁。
三种同步类型:数据同步、设备同步、任务同步。

C++多线程编程(6)合作与同步


 

4.同步关系:SS、FS、SF、FF

C++多线程编程(6)合作与同步

5.进程同步机制:信号量、条件变量、临界区
  结合SS、FS、SF、FF同步关系与同步机制来消除在多线程编程中发生竞争条件和死锁的可能性。
  信号量(semaphore):特殊的受保护封装的变量。用于帮助线程或进程同步访问一些共享、可修改内存

块或控制对一些设备的访问。充当共享资源的一种钥匙,这把钥匙只能由一个线程或进程拥有,其他进程

或线程必须等待资源被释放。具有此信号量的线程就被认为占有此信号量,任何试图占有这个信号量的其

他线程或进程一般都被阻塞,一直等到信号量的占有者释放它为止。
 两种信号量:二进制信号量(值:0,1,执行操作:P(Mutex)减量、V(Mutex)增量)、计数信号量(保证以非

负整数值出现,执行操作:P,V,lock(),unlock(),wait(),down(),up())
信号量操作是原子性或不可分割性的操作。一旦开始了信号量操作,它就保证在不被抢占的情况下运行到

完成。程序员不能用普通布尔变量和布尔操作取代特殊的信号量变量和信号量操作,因为大部分操作不是

原子性的,它可能被中断。

 

6.信号量类型(3种):

这些机制的用途:防止竞争条件和死锁。

C++多线程编程(6)合作与同步

7.临界区:共享数据块被修改,或者共享资源被更改的区域,是创建竞争条件和死锁之地。如果正确管理,

就可以避免使用并发技术时可能发生的大部分缺陷。

 

8.互斥:保护程序中的临界区,将它们锁定,只允许一个线程或进程在某一时刻访问它,不让其他线程或进程访问。实现互斥机制通常称互斥量(mutex)。
互斥信号量包含实际可行信号量机制的所有必需操作:5种。
a.初始化(分配内存并赋予内存初始值,决定信号量是否被占有、私有或共享)

b.锁定请求(互斥量被锁定时导致获得锁定的线程具有该互斥量的占有权,其他未经授权的线程均被阻塞)
c.Try锁定(测试互斥量,检查互斥量的占有权。如果互斥量被占有没有阻塞线程,则返回错误;如果没有

被占有,则锁定成功。可以等待互斥量一段时间,在这段时间内,它未取消锁定,则线程继续执行)
d.取消锁定(互斥量释放或取消锁定请求将导致其他线程等待该互斥量的取消锁定,当其中一个线程获得

了互斥量的占有权时,所有剩下的线程都仍然等待访问权的再次阻塞)
e.析构(释放与互斥量相关的内存。如果互斥量被占有或某线程等待着该互斥量,可以销毁或关闭内存)

C++多线程编程(6)合作与同步


 

9.互斥量初始化:同步变量不会像常规变量一样保证得到初始化,互斥量初始化可能也会失败,原因有多

种。在锁定、取消锁定或销毁操作中使用任何信号量之前,确保信号量最初正确初始化了。互斥量初始化

通常由某种类型的函数调用来完成。
//POSIX互斥量初始化
pthread_mutex_t MHandle
pthread_mutex_init(&MHandle,Null);
//OS2互斥量初始化
HMTX MHandle
DosCreateMutexsem(NULL,&MHandle,0,0);

 

10.自愿互斥量策略:自愿调用pthread_mutex_lock来保护临界区某些线程对象的状态免遭破坏。使用互斥量访问同步化是一种编程策略,根据实际来实施。自愿使用互斥量来同步可能是多线程环境中主要缺陷产生的原因,程序员可能没有意识到保护临界区正被访问,这个问题可以通过C++中的封装技术来解决。

 

11.互斥信号量try_lock请求:为了防止线程在已被占有的互斥量上一直阻塞,调用try_lock()互斥量函数测试该互斥量的占有权。如果已被占有,返回一个错误,但不会阻塞线程。如果没有被占有,则锁定成功。

 

12.互斥信号量取消锁定(unlock)请求:只有互斥量的占有者可以取消锁定或释放互斥量。一旦线程获得互斥量占有权,仍希望访问互斥量的所有剩余线程再次被阻塞。如果同时还有其他线程在该互斥量上阻塞,则具有最高优先级的线程交付这个互斥量。如所有阻塞线程都具有相同优先权,线程按FIFO方式获取可用互斥量的访问权。

 

13.互斥信号量析构:释放或取消锁定互斥量不会释放与互斥量关联的内存。释放只是放弃互斥量的占有权,使其他占有者可以锁定他。如果要释放互斥量内存,必须销毁或关闭互斥量。如果互斥量仍被占有或存在阻塞线程还在等待该互斥量的释放,就不能销毁或关闭该互斥量。

【程序演示】互斥量的应用:

C++多线程编程(6)合作与同步

 

14.事件互斥量和条件变量:支持一种线程间的广播机制,允许一个线程广播给另一个线程告知某事件已经发生。当一个线程锁定了一个事件互斥量,它将阻塞,直到它接到了一条广播,告知它可以继续为止。

Win32环境: CreateEvent() 创建事件信号量对象(或命名事件信号量对象);OpenEvent()名字用作它的参数,从一个无关进程打开一个事件信号量对象;SetEvent() 事件信号量对象状态更改为被通知,如已通知,函数将无作用;ResetEvent()重置事件信号量对象,更改对象状态为被通知;PulseEvent()将对象状态更改为被通知,释放所有等待线程,然后将对象状态改为未被通知;WaitForSingleObject() 导致线程一直等待到对象被通知,将对象指定为参数之一;WaitForMultipleObjects() 导致线程等待一个包含一个或多个同步对象的数组。 

【注意】每种环境中都必须创建事件互斥量,然后可以执行3个主要操作:事件互斥量等待、延后和销毁。互斥量和事件互斥量(或条件变量)区别:互斥量只是导致一个线程一直阻塞到该互斥量被释放为止;而事件互斥量让一个或多个线程一直等到条件满足为止,或等到一个事件或多个事件的发生。

【程序演示】 搜索匹配关键字列表的文本文件(TXT),如果搜到是文本文件则添加到文件队列中,如果从文件队列中搜索到了需要的关键字,那么从文件队列中删除该文件。这时候,需要等待“文本文件添加到文件队列中”这个事件的发生才能锁定该事件互斥量并进行下一步文本文件搜索匹配关键字。C++多线程编程(6)合作与同步
C++多线程编程(6)合作与同步
C++多线程编程(6)合作与同步


15.无限延迟(indefinite postponement):死锁的特例(单进程死锁),非锁定资源所产生的,线程可能等待着某个事件的发生,或某个条件的满足,但情况却是事件永远也不会发生或者条件永远不会满足。

 

16.避免竞争条件:4种
  a.不要使用可能同时位于临界区内的两个进程
  b.不要依赖对CPU的速度做出的任何假设
  c.不要让临界区外部停止的进程阻塞其他进程
  d.不要让进城等待任意长的时间进入其临界区。

 

17.死锁必须的先行条件:4个
  a.进程声明排他性控制他们需求的资源
  b.进程在等待其他资源的释放时占有资源
  c.资源无法强行从进程中删除
  d.存在一个循环等待条件

 

18.解决死锁:应用定时互斥量、事件变量、同步变量以及信号量等这些定时同步机制.也可以通过使用C++ IPC(进程间控制)、ITC组件以及多线程架构,可以去掉应用程序中的竞争条件和死锁。



推荐阅读
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 本文讨论了读书的目的以及学习算法的重要性,并介绍了两个算法:除法速算和约瑟夫环的数学算法。同时,通过具体的例子和推理,解释了为什么x=x+k序列中的第一个人的位置为k,以及序列2和序列3的关系。通过学习算法,可以提高思维能力和解决问题的能力。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
author-avatar
香港买iphone
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有