【读书笔记】Windows CE嵌入式系统_【4】_线程同步

本文主要介绍了Windows CE嵌入式系统中的线程同步机制,包括Mutex、Semaphore、Event、Critical Section以及互锁函数。这些同步对象用于管理线程间的资源访问,确保并发执行时的数据一致性。Mutex提供互斥访问,Semaphore作为信号灯具有引用计数,Event用于触发事件,而Critical Section和互锁函数则在用户态提供高效但不跨进程的同步方式。
摘要由CSDN通过智能技术生成

开篇

1、WinCE提供了Mutex,Event 和 Semaphore 三种内核机制来实现线程之间的同步。

     WinCE提供了两种用户态下的同步方法:Critical Section 和互锁函数(Interlocked Functions)-----------不能跨进程,运行效率高

2、同步对象有两种状态:

  • 通知(Signaled)                   
  • 未通知(Non-signaled)     -------表示同步对象被占用

3、等待同步对象函数



WaitForSingleObject()用来等待单个同步对象,WaitForMultipleObjects()用来等待多个同步对象。

参数dwMilliseconds,用来指定等待时间,单位百毫秒。如果设置成INFINITE,则一直等待同步对象变为通知状态。如果设置为其它值,则当等待时间耗尽返回,即使同步对象依然处于未通知状态。

Mutex--互斥(内核态)

如果某些共享资源同时 只能被一个线程访问,则优选Mutex。


孙鑫教学视频第15课中的代码
#include <windows.h>
#include <iostream.h>
//声明线程入口函数原型
DWORD WINAPI Fun1Proc(  LPVOID lpParameter );
DWORD WINAPI Fun2Proc(  LPVOID lpParameter );
int tickets = 100; //要销售的票数还剩下100张
//这100张票由Fun1Proc与Fun2Proc两个线程负责销售

HANDLE hMutex;//互斥对象句柄

void main()
{	
	HANDLE  hThread1,hThread2;
	hThread1 = CreateThread(
		NULL,	//使用缺省的安全性
		0,		//指定初始提交栈的大小
		Fun1Proc,//指定线程入口函数地址
		NULL,	//传递给线程的参数
		0,		//附加标记,0表示线程创建后立即运行
		NULL);	//线程ID,在Win98/95中不能设置为NULL
	CloseHandle(hThread1);
	hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
	CloseHandle(hThread2);
//	cout<<"main thread is running"<<endl;
//	hMutex = CreateMutex(NULL, FALSE,NULL);
		//创建一个匿名的互斥对象
	hMutex = CreateMutex(NULL, TRUE,"MuName");
		//创建一个命名的互斥对象
	if(hMutex)
	{//判断是不是第一次创建的互斥对象
		if(ERROR_ALREADY_EXISTS == GetLastError())
		{//如果为真,说明互斥对象已经创建
			cout<<"已经有一个实例在运行了,只能有一个实例运行同时运行。"<<endl;
			return;
		}
	}
	WaitForSingleObject(hMutex,INFINITE);
		//因为请求的互斥对象线程ID与拥有互斥对象线程ID相同,
		//可以再次请求成功,计数器加1
	ReleaseMutex(hMutex);  //第一次释放,计数器减1,但仍有信号
	ReleaseMutex(hMutex);  //再一次释放,计数器为零

	while(tickets>0)	{ Sleep(4000);}
}//endof main()
/*------------实现线程入口函数Fun1Proc---------------*/
DWORD WINAPI Fun1Proc(  LPVOID lpParameter )
{	
	while(TRUE)
	{
		WaitForSingleObject(hMutex,INFINITE);
			//请求互斥对象
		if(tickets>0)
		{Sleep(1);
			cout<<"thread 1 sell ticket: ";
			cout<<tickets--<<endl;
		}
		else  
			break;
		ReleaseMutex(hMutex);

	}
	return 0;
}	///endof Fun1Proc()

/*-----------实现线程入口函数Fun2Proc--------------*/
DWORD WINAPI Fun2Proc(  LPVOID lpParameter )
{	
	while(TRUE)
	{
		WaitForSingleObject(hMutex,INFINITE);
		if(tickets>0)
		{Sleep(1);
			cout<<"thread 2 sell ticket: ";
			cout<<tickets--<<endl;
		}
		else
			break;
		ReleaseMutex(hMutex);
	}
	return 0;
}	///endof Fun1Proc()

Semaphore----信标或信号灯,→→带有引用计数的Mutex (内核态)

如果共享资源同时只能被 固定数量的线程使用,那么优选Semaphore。



占用时,lInitialCount,增加1;施放时,lInitialCount,减少一。

Event-----事件(内核态)




孙鑫教学视频16课中的源码
#include <windows.h>
#include <iostream.h>

int ticket=100;
HANDLE g_hEvent;//保存事件对象句柄

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

void main()
{
	HANDLE thread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
	HANDLE thread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
	
	CloseHandle(thread1);
	CloseHandle(thread2);
	//创建事件对象,可用命名事件对象来控制只运行一个实例
	g_hEvent=CreateEvent(NULL,
		FALSE,	//TRUE人工重置,FALSE 自动重置
		FALSE,	//初始化状态,TURE信号状态,FALSE非信号状态
		"tickets");	//事件对象命名,NULL表示匿名
	if(g_hEvent)
	{
		if(ERROR_ALREADY_EXISTS == GetLastError())
		{
			cout<<"Only one instance can run!"<<endl;
			return;
		}
	}
	SetEvent(g_hEvent);//将事件设置为有信号状态
	Sleep(4000);
	CloseHandle(g_hEvent);
	
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
	WaitForSingleObject(g_hEvent,INFINITE);
	
	while(ticket)
	{
		cout<<"thread1 sells : "<<ticket--<<endl;
		Sleep(1);
		SetEvent(g_hEvent);
	}
	
	return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
	WaitForSingleObject(g_hEvent,INFINITE);
	while(ticket)
	{
		cout<<"thread2 sells : "<<ticket--<<endl;
		Sleep(1);
    SetEvent(g_hEvent);
	}
	
	return 0;
}

Critical Section ---------临界区(用户态)

Critical Section 是应用程序分配的一个数据结构。用来把一段代码标记为临界区。

在使用Critical Section时,一般为每一个共享资源分配一个Critical Section变量。应该把尽可能少的代码放在Critical Section中。

互锁函数




示例代码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值