线程间如何通信/同步?之前在一个小系列中介绍了进程间通信的方法,所以有些小伙伴对进程间通信和同步的方法很好奇。没关系。下面小编将继续给大家科普下进程间通信和同步的方法。
线程间通信及同步方法介绍:
一、线程间的通信方式
1、使用全局变量
全局变量最好声明为volatile,主要是因为多线程可能会改变全局变量。
2、使用消息实现通信
在Windows编程中,每个线程都可以有自己的消息队列(UI线程默认有自己的消息队列和消息循环,工作线程需要手动实现消息循环),所以消息可以用来在线程之间传递sendMessage和postMessage。
1)定义消息# define WM _ thread _ send msg=WM _ user 20;
2)添加消息函数声明afx _ msg int ontendmsg();();
3)添加消息映射ON_MESSAGE(WM_THREAD_SENDMSG,ontsm);
4)增加了OnTSM()的实现功能;
5)在线程函数中加入PostMessage消息Post函数。
3、使用事件CEvent类实现线程间通信
事件对象有两种状态:有信号和无信号。线程可以监视处于信号状态的事件,以便在适当的时间对事件执行操作。
1)创建CEvent类的对象:CEvent threadStart默认处于非通信状态;
2)threadStart。SetEvent();使其处于交流状态;
3)调用WaitForSingleObject()来监视CEvent对象。
二、线程间的同步方式
每个线程都可以访问进程中的公共变量和资源,所以在使用多线程的过程中需要注意的问题是如何防止两个或多个线程同时访问同一个数据,以免破坏数据的完整性。
数据之间的相互约束包括:
1.直接约束关系,即一个线程的处理结果是另一个线程的输入,所以直接约束线程,这可以称为同步关系。
2.间接约束关系,即两个线程需要访问同一个资源,而这个资源只能由一个线程同时访问。这种关系被称为线程之间对资源的互斥访问。从某种意义上说,互斥是约束关系较小的同步。
线程间同步有四种方式:
1、临界区
临界区对应于一个cccritical section对象。当线程需要访问受保护的数据时,会调用EnterCriticalSection函数。保护数据的操作完成后,调用LeaveCriticalSection函数,释放临界段对象的所有权,让另一个线程抢占临界段对象,访问被保护的数据。
PS:关键段对象记录了拥有该对象的线程句柄,即它有“线程所有权”的概念,即进入代码段的线程可以在离开前反复进入关键代码区。因此,密钥段可以用于线程之间的互斥,但不能用于同步(同步需要在一个线程中进入,在另一个线程中离开)。
2、互斥量
互斥和临界区类似,但是使用起来相对复杂(互斥是一个内核对象)。它不仅可以实现同一应用程序的线程之间的同步,还可以实现不同进程之间的同步,从而实现资源的安全共享。
PS:
1)互斥也有线程所有权的概念,所以只能访问线程间互斥的资源,不会因为线程同步;
2)由于互斥体是一个内核对象,可以在进程间进行通信,它还有一个很好的特点,那就是完美解决了进程间通信时的“放弃”问题。
3、信号量
信号量的使用类似于互斥,只是它可以允许多个线程同时访问同一个资源,PV操作。
PS:事件可以完美解决线程之间的同步问题,信号量也属于内核对象,可以用于进程间通信。
4、事件
事件分为手动设置事件和自动设置事件。在事件事件内部,它包含一个使用计数(所有内核对象都有),一个布尔值指示事件是手动设置的还是自动设置的,另一个布尔值指示事件是否被触发。由设置事件()触发,设置为不由重置事件()触发。
PS:事件是内核对象,可以解决线程之间的同步问题,所以也可以解决互斥问题。
线程之间的通信和同步方法到此结束。关于线程同步的更多文章,可以参考:《线程同步的方法有哪些?Linux下实现线程同步的三种方法》