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

时间:2022-04-09 06:55:33

开篇

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

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

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

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

3、等待同步对象函数
【读书笔记】Windows CE嵌入式系统_【4】_线程同步

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

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

Mutex--互斥(内核态)

如果某些共享资源同时只能被一个线程访问,则优选Mutex。 【读书笔记】Windows CE嵌入式系统_【4】_线程同步

孙鑫教学视频第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。
【读书笔记】Windows CE嵌入式系统_【4】_线程同步

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

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


【读书笔记】Windows CE嵌入式系统_【4】_线程同步
【读书笔记】Windows CE嵌入式系统_【4】_线程同步
孙鑫教学视频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 是应用程序分配的一个数据结构。用来把一段代码标记为临界区。
【读书笔记】Windows CE嵌入式系统_【4】_线程同步
在使用Critical Section时,一般为每一个共享资源分配一个Critical Section变量。应该把尽可能少的代码放在Critical Section中。

互锁函数

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

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