四种方式实现线程同步

  • 四种线程同步方式比较

  • 代码



/****************使用以下四种方式实现线程同步******************
                (1)事件(Event); 
                (2)信号量(semaphore); 
                (3)互斥量(mutex); 
                (4)临界区(Critical section)
**************************************************************/

#include "stdafx.h"
#include <windows.h>
#include <iostream>
 
 
using namespace std;
 
DWORD WINAPI myfun1(LPVOID lpParameter); //声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter);
 
/************使用临界区对象实现多线程同步***************
临界区被初始化后,当程序进入临界区后便拥有临界区的所有权,其余线程无权进入只能等对方释放临界区之后,方可进入临界区拥有其所有权再对临界区进行操作
InitializeCriticalSection()初始化临界区;
EnterCriticalSection()进入临界区;
LeaveCriticalSection()释放临界区所有权并离开临界区;
注意:上述是windows API中相关函数,CCriticalSection类是MFC中定义的临界区类,需要在MFC程序中使用(此程序为控制台程序无法使用MFC类),可以操作临界区,lock锁定临界区、unlock释放临界区
	  临界区为依次访问,不能实现其中一个线程一释放临界区就会被另一个线程访问临界区!不能实现实时监听
********************************************************/
 
/************使用事件对象实现多线程同步***************
事件对象是指用户在程序中使用内核对象的有无信号状态实现线程的同步临界区被初始化后,当程序进入临界区后便拥有临界区的所有权,其余线程无权进入只能等对方释放临界区之后,方可进入临界区拥有其所有权再对临界区进行操作
CreatEvent()创建并返回事件对象;
SetEvent()将指定的事件设置为有信号状态(有信号状态下其余线程可以访问);
ResetEvent()将指定的事件设置为无信号状态;
除SetEvent函数外,WaitForSingleObject函数等待指定事件。
注意:上述是Windows API函数,CEvent类是MFC实现事件对象的类
	  事件对象为立即访问,一旦事件对象被设置为有信号 立刻会被其余线程访问!能实现实时监听
********************************************************/
 
/************使用互斥对象实现多线程同步***************
互斥对象还可以在进程间使用,在实现线程同步时包含一个线程ID和一个计数器,线程ID表示拥有互斥对象的线程,计数器表示该互斥对象被同一线程所使用次数
CreatMutex()创建并返回互斥对象;
ReleaseMutex()释放互斥对象句柄;
WaitForSingleObject()对该对象进行请求。
注意:上述是Windows API函数,CMutex类是MFC中的互斥对象类
	  互斥对象为立即访问,一旦互斥对象被释放 立刻会被其它正在等待的线程访问!能实现实时监听
********************************************************/

/************使用信号量实现多线程同步***************
CreateSemaphore()创建并返回信号量;
ReleaseSemaphore()释放信号量句柄;
WaitForSingleObject()对该对象进行请求。
********************************************************/
 
static int a=0;
CRITICAL_SECTION section;//定义临界区对象(Windows API)
HANDLE hevent;//定义全局事件变量句柄
HANDLE hmutex;//定义全局互斥对象句柄
HANDLE hSemaphore;  //定义信号量句柄
 
int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE h1,h2;//声明句柄变量
	//InitializeCriticalSection(&section);//初始化临界区对象(需要在线程前初始化)
 
	//hevent=CreateEvent(NULL,FALSE,false,NULL);//创建事件并返回句柄
	//SetEvent(hevent);//设置事件为有信号状态
 
	//hmutex=CreateMutex(NULL,false,NULL);//创建互斥对象并返回其句柄

	 hSemaphore = CreateSemaphore(NULL, 1, 100, "sema");//创建信号量
 
	h1=CreateThread(NULL,0,myfun1,NULL,0,NULL);//创建线程1
	cout<<"线程1开始运行!\n"<<endl;
	h2=CreateThread(NULL,0,myfun2,NULL,0,NULL);//创建线程2
	cout<<"线程2开始运行!"<<endl;
 
	//关闭线程句柄对象
	CloseHandle(h1);
	CloseHandle(h2);
 
	while (1)
	{
 
		if (getchar()=='q')//如果用户输入字符q
		{
			//DeleteCriticalSection(&section);//删除临界区对象
			return 0;//程序正常退出
		}
		else
		{
			Sleep(100);//程序睡眠
		}
	}
	return 0;
 
}
 
//分别实现线程函数,并返回值
DWORD WINAPI myfun1(LPVOID lpParameter)
{
	long count;
	while (true)
	{
		//EnterCriticalSection(&section);          //进入临界区
 
		//WaitForSingleObject(hevent,INFINITE);   //使线程进入等待状态,直到事件对象变为已通知状态为止。INFINITE表示永久等待
		//ResetEvent(hevent);                     //设置事件对象为无信号状态
 
		//WaitForSingleObject(hmutex,INFINITE);//使线程进入等待状态,直到互斥对象变为已通知状态为止。INFINITE表示永久等待

		 WaitForSingleObject(hSemaphore, INFINITE);  //等待信号量为有信号状态
 
		a++;
		if (a<1000)
		{
			cout<<"线程1正在计数"<<a<<endl;
			//LeaveCriticalSection(&section);//离开临界区
 
			//SetEvent(hevent);
 
			//ReleaseMutex(hmutex);//释放互斥对象句柄

			ReleaseSemaphore(hSemaphore, 1, &count); //释放信号量

		}
		else
		{
			//a=0;
			//LeaveCriticalSection(&section);
 
			//SetEvent(hevent);
 
			//ReleaseMutex(hmutex);//释放互斥对象句柄

			ReleaseSemaphore(hSemaphore, 1, &count);  //释放信号量

			break;
		}
 
	}
 
	return 0;
}
 
DWORD WINAPI myfun2(LPVOID lpParameter)
{
	long count;
	while (true)
	{
		//EnterCriticalSection(&section);//进入临界区
 
		//WaitForSingleObject(hevent,INFINITE);//请求事件对象
		//ResetEvent(hevent);//设置事件对象为无信号状态
 
		//WaitForSingleObject(hmutex,INFINITE);使线程进入等待状态,直到互斥对象变为已通知状态为止。INFINITE表示永久等待
 
		 WaitForSingleObject(hSemaphore, INFINITE);  //等待信号量为有信号状态
		a++;
		if (a<1000)
		{
			cout<<"线程2正在计数"<<a<<endl;
			//LeaveCriticalSection(&section);//离开临界区
 
			//SetEvent(hevent);
 
			//ReleaseMutex(hmutex);//释放互斥对象句柄

			ReleaseSemaphore(hSemaphore, 1, &count);  //释放信号量
		}
		else
		{
			//LeaveCriticalSection(&section);//离开临界区,当计数a大于1000时退出循环
 
			//SetEvent(hevent);
 
			//ReleaseMutex(hmutex);//释放互斥对象句柄

			ReleaseSemaphore(hSemaphore, 1, &count);  //释放信号量

			break;
		}
 
	}
 
	return 0;
}

 

线程同步四种方式是: 1. 互斥锁(Mutex):通过对共享资源加锁,保证在同一时刻只有一个线程可以访问该资源,其他线程需要等待锁释放后才能访问。这种方式可以避免多个线程同时修改共享资源导致的数据不一致问题。 2. 信号量(Semaphore):通过设置一个计数器,控制同时访问共享资源的线程数量。当计数器不为零时,线程可以访问资源;当计数器为零时,线程需要等待其他线程释放资源后才能访问。信号量可以用于控制线程的并发数量。 3. 事件(Event):通过一个或多个标志来通知线程是否可以继续执行。线程可以等待事件的触发,一旦触发,线程就可以继续执行。事件可以用于线程之间的通信和同步。 4. 条件变量(Condition Variable):用于线程之间的通信和同步,一个线程等待某个条件满足时可以阻塞自己,直到其他线程通知该条件已经满足,然后线程可以继续执行。条件变量通常和互斥锁一起使用,以实现线程之间的同步和协作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [线程同步四种方式](https://blog.csdn.net/chanlp129/article/details/125357577)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [[面试]进程同步的四种方法](https://blog.csdn.net/wuhuagu_wuhuaguo/article/details/78591330)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的路飞桑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值