1.CRITICAL_SECTION:不能锁定资源,只是同步代码
简单说,当一个线程执行了EnterCritialSection之后,cs里面的信息便被修改了,以指明哪一个线程占用了它。而此时,并没有任何资源被“锁定”。只不过,在这个线程尚未执行LeaveCriticalSection之前,其它线程碰到EnterCritialSection语句的话,就会处于等待状态,相当于线程被挂起了。 这种情况下,就起到了保护共享资源的作用。
也正由于CRITICAL_SECTION是这样发挥作用的,所以,必须把每一个线程中访问共享资源的语句都放在EnterCritialSection和LeaveCriticalSection之间。这是初学者很容易忽略的地方。
CRITICAL_SECTION临界区的使用在线程同步中应该算是比较简单,在使用临界区的时候要注意,每一个共享资源就有一个CRITICAL_SECTION,如果要一次访问多个共享变量,各个线程要保证访问的顺序一致,如果不一致,很可能发生死锁。
1: InitializeCriticalSection(&g_cs_listview); 2: InitializeCriticalSectionAndSpinCount(&g_cs_listview); 3: DeleteCriticalSection(&g_cs_listview); 4: TryEnterCriticalSection(&g_cs_listview); 5: EnterCriticalSection(&g_cs_listview); 6: LeaveCriticalSection(&g_cs_listview);
注意:假如多个线程都在等待同一个critical section,究竟哪个线程会先获得它的所有权是不一定的,cirtical section在这方面没有保证.
2.Semaphore信号量:
Semaphore对象用来控制对资源的并发访问数。内部有个计数器,当值>=0设置了信号,==0清除信号。每次调用wait函数计数器都减1。调用ReleaseSemaphore时将计数器设置为lREleaseCount的指定的值。
// 创建信号量,且设置为1表示每次只能有一个线程访问;
// 如果创建失败表示该"semaphore_test"标示符在别的进程中创建,可用OpenSemaphore来打开信号量
// CreateSemaphore(为安全属性,Semaphore的初始值,最大值,对象的名字)
HANDLE hSe = CreateSemaphore(NULL, 1, 1, "semaphore_test");
// 释放本进程的信号量
// ReleaseSemaphore(句柄,要增加的数值,用于返回之前的计算值)
ReleaseSemaphore(hSe, 1, NULL);
// 等待一个对象是否可用;
ret = WaitForSingleObject(hSe, 1000);
case WAIT_OBJECT_0: // 如果是WaitForSingleObject第一个对象就是等待的句柄
case WAIT_TIMEOUT: // 超时
1: #include "stdafx.h" 2: #include 3: #include 4: using namespace std; 5: 6: const int MAX_RUNNUM = 3; //最多运行实例个数 7: void PrintInfo() 8: { 9: char c; 10: cout > c; 15: if (c == 's') 16: { 17: break; 18: } 19: Sleep(10); 20: } 21: } 22: int main(int argc, char* argv[]) 23: { 24: HANDLE hSe = CreateSemaphore(NULL, MAX_RUNNUM, MAX_RUNNUM, "semaphore_test"); 25: DWORD ret = 0; 26: if (hSe == NULL) 27: { 28: cout
3.Mutex-互斥体
mutex互斥体的意思,当一个线程持有一个Mutex时,其它线程申请持有同一个Mutex会被阻塞在一个队列中,当互斥体释放后队列中的第一个线程首先获得使用权。
//创建一个互斥体
//CreateMutex(安全描述符, Mutex的持有者设置为调用线程, Mutex的名字)
//如果创建失败表示该名称的mutex标示符在别的进程中创建,可用OpenMutex来打开信号量
HANDLE hmutex = CreateMutex(NULL, false, NULL);
//销毁互斥体
CloseHandle(hmutex);
// 等待一个对象是否可用;
ret = WaitForSingleObject(hmutex, 1000);
case WAIT_OBJECT_0: // 如果是WaitForSingleObject第一个对象就是等待的句柄
case WAIT_TIMEOUT: // 超时
1: //互斥体通常用于多进程之间的同步问题 2: 3: //程序运行单个实例: 4: #include "stdafx.h" 5: #include 6: #include 7: #include 8: using namespace std; 9: 10: //当输入s或者c时候结束程序 11: void PrintInfo(HANDLE& h, char t) 12: { 13: char c; 14: while (1) 15: { 16: cin >> c; 17: if (c == t) 18: { 19: ReleaseMutex(h); 20: CloseHandle(h); 21: break; 22: } 23: Sleep(100); 24: } 25: } 26: int main(int argc, char* argv[]) 27: { 28: //创建mutex,当已经程序发现已经有这个mutex时候,就相当于openmutex 29: HANDLE hHandle = CreateMutex(NULL, FALSE, "mutex_test"); 30: if (GetLastError() == ERROR_ALREADY_EXISTS) 31: { 32: cout
4.Event事件
创建一个事件:
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
第1个参数:安全属性大多默认为null
第2个参数:是否必须手工复位到无信号状态,false=线程结束就自动设置无信号
第3个参数:默认是否有信号;true有信号,false无信号
第4个参数:对象名称,大多为null
释放一个事件:
CloseHandle(hEvent);
设置一个事件有信号:
setEvent(hEvent); //变成有信号状态
pluseEvent(hEvent); //一个脉冲:从无信号变成有信号再变成无信号
复位一个Event对象
ResetEvent(hEvent)
等待一个或多个事件有信号:
WaitForSingleObject(handle, INFINITE/*等待时间*/);
参数handle:可以(Event,Mutex,Process,Thread,Semaphore)等等; thread的join就是等thread实现的
参数INFINITE:是等待超时时间,INFINITE是死等
WaitForMultipleObjects(nCount, handle_array, false, INFINITE/*等待时间*/);
参数nCount:是监测event的个数
参数handle_array:是event数组
参数false:表示有一个信号就返回,true是等待所有事件都有信号才返回
参数INFINITE:是等待超时时间,INFINITE是死等
wait…返回值:
WAIT_OBJECT_0:表示第一个事件
WAIT_TIMEOUT:超时
WAIT_ABANDONED:
1: /*简单示例,一个线程不停读取用户输入并放入message列表, 2: 另一个线程模拟将message发送出去,如果没有消息,则发送线程处于阻塞状态等待, 3: 一旦有消息录入,输入线程将event置位,发送线程即被激活并逐个发送消息。*/ 4: #include "stdafx.h" 5: #include 6: #include 7: #include 8: #include 9: #include 10: using namespace std; 11: 12: #ifdef _UNICODE 13: typedef wstring tstring; 14: #define tcout wcout 15: #define tcin wcin 16: #else 17: typedef string tstring; 18: #define tcout cout 19: #define tcin cin 20: #endif /* _UNICODE */ 21: 22: typedef list StringList; 23: 24: HANDLE hMutex = NULL; 25: HANDLE hEvent = NULL; 26: HANDLE hSendThread = NULL; 27: StringList messages; 28: 29: bool isRunning; 30: 31: DWORD WINAPI SendThreadProc(LPVOID lpThreadParameter) 32: { 33: DWORD dw; 34: while(isRunning) 35: { 36: dw = WaitForSingleObject(hEvent, INFINITE); 37: if(dw != WAIT_OBJECT_0) 38: { 39: tcout > s; 78: if(s == _T("quit")) 79: { 80: isRunning = true; 81: break; 82: } 83: 84: DWORD dw = WaitForSingleObject(hMutex, INFINITE); 85: if(WAIT_OBJECT_0 != dw && WAIT_ABANDONED != dw) 86: { 87: tcout
1.CRITICAL_SECTION:不能锁定资源,只是同步代码
简单说,当一个线程执行了EnterCritialSection之后,cs里面的信息便被修改了,以指明哪一个线程占用了它。而此时,并没有任何资源被“锁定”。只不过,在这个线程尚未执行LeaveCriticalSection之前,其它线程碰到EnterCritialSection语句的话,就会处于等待状态,相当于线程被挂起了。 这种情况下,就起到了保护共享资源的作用。
也正由于CRITICAL_SECTION是这样发挥作用的,所以,必须把每一个线程中访问共享资源的语句都放在EnterCritialSection和LeaveCriticalSection之间。这是初学者很容易忽略的地方。
CRITICAL_SECTION临界区的使用在线程同步中应该算是比较简单,在使用临界区的时候要注意,每一个共享资源就有一个CRITICAL_SECTION,如果要一次访问多个共享变量,各个线程要保证访问的顺序一致,如果不一致,很可能发生死锁。
1: InitializeCriticalSection(&g_cs_listview); 2: InitializeCriticalSectionAndSpinCount(&g_cs_listview); 3: DeleteCriticalSection(&g_cs_listview); 4: TryEnterCriticalSection(&g_cs_listview); 5: EnterCriticalSection(&g_cs_listview); 6: LeaveCriticalSection(&g_cs_listview);
注意:假如多个线程都在等待同一个critical section,究竟哪个线程会先获得它的所有权是不一定的,cirtical section在这方面没有保证.
2.Semaphore信号量:
Semaphore对象用来控制对资源的并发访问数。内部有个计数器,当值>=0设置了信号,==0清除信号。每次调用wait函数计数器都减1。调用ReleaseSemaphore时将计数器设置为lREleaseCount的指定的值。
// 创建信号量,且设置为1表示每次只能有一个线程访问;
// 如果创建失败表示该"semaphore_test"标示符在别的进程中创建,可用OpenSemaphore来打开信号量
// CreateSemaphore(为安全属性,Semaphore的初始值,最大值,对象的名字)
HANDLE hSe = CreateSemaphore(NULL, 1, 1, "semaphore_test");
// 释放本进程的信号量
// ReleaseSemaphore(句柄,要增加的数值,用于返回之前的计算值)
ReleaseSemaphore(hSe, 1, NULL);
// 等待一个对象是否可用;
ret = WaitForSingleObject(hSe, 1000);
case WAIT_OBJECT_0: // 如果是WaitForSingleObject第一个对象就是等待的句柄
case WAIT_TIMEOUT: // 超时
1: #include "stdafx.h" 2: #include 3: #include 4: using namespace std; 5: 6: const int MAX_RUNNUM = 3; //最多运行实例个数 7: void PrintInfo() 8: { 9: char c; 10: cout > c; 15: if (c == 's') 16: { 17: break; 18: } 19: Sleep(10); 20: } 21: } 22: int main(int argc, char* argv[]) 23: { 24: HANDLE hSe = CreateSemaphore(NULL, MAX_RUNNUM, MAX_RUNNUM, "semaphore_test"); 25: DWORD ret = 0; 26: if (hSe == NULL) 27: { 28: cout
3.Mutex-互斥体
mutex互斥体的意思,当一个线程持有一个Mutex时,其它线程申请持有同一个Mutex会被阻塞在一个队列中,当互斥体释放后队列中的第一个线程首先获得使用权。
//创建一个互斥体
//CreateMutex(安全描述符, Mutex的持有者设置为调用线程, Mutex的名字)
//如果创建失败表示该名称的mutex标示符在别的进程中创建,可用OpenMutex来打开信号量
HANDLE hmutex = CreateMutex(NULL, false, NULL);
//销毁互斥体
CloseHandle(hmutex);
// 等待一个对象是否可用;
ret = WaitForSingleObject(hmutex, 1000);
case WAIT_OBJECT_0: // 如果是WaitForSingleObject第一个对象就是等待的句柄
case WAIT_TIMEOUT: // 超时
1: //互斥体通常用于多进程之间的同步问题 2: 3: //程序运行单个实例: 4: #include "stdafx.h" 5: #include 6: #include 7: #include 8: using namespace std; 9: 10: //当输入s或者c时候结束程序 11: void PrintInfo(HANDLE& h, char t) 12: { 13: char c; 14: while (1) 15: { 16: cin >> c; 17: if (c == t) 18: { 19: ReleaseMutex(h); 20: CloseHandle(h); 21: break; 22: } 23: Sleep(100); 24: } 25: } 26: int main(int argc, char* argv[]) 27: { 28: //创建mutex,当已经程序发现已经有这个mutex时候,就相当于openmutex 29: HANDLE hHandle = CreateMutex(NULL, FALSE, "mutex_test"); 30: if (GetLastError() == ERROR_ALREADY_EXISTS) 31: { 32: cout
4.Event事件
创建一个事件:
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
第1个参数:安全属性大多默认为null
第2个参数:是否必须手工复位到无信号状态,false=线程结束就自动设置无信号
第3个参数:默认是否有信号;true有信号,false无信号
第4个参数:对象名称,大多为null
释放一个事件:
CloseHandle(hEvent);
设置一个事件有信号:
setEvent(hEvent); //变成有信号状态
pluseEvent(hEvent); //一个脉冲:从无信号变成有信号再变成无信号
复位一个Event对象
ResetEvent(hEvent)
等待一个或多个事件有信号:
WaitForSingleObject(handle, INFINITE/*等待时间*/);
参数handle:可以(Event,Mutex,Process,Thread,Semaphore)等等; thread的join就是等thread实现的
参数INFINITE:是等待超时时间,INFINITE是死等
WaitForMultipleObjects(nCount, handle_array, false, INFINITE/*等待时间*/);
参数nCount:是监测event的个数
参数handle_array:是event数组
参数false:表示有一个信号就返回,true是等待所有事件都有信号才返回
参数INFINITE:是等待超时时间,INFINITE是死等
wait…返回值:
WAIT_OBJECT_0:表示第一个事件
WAIT_TIMEOUT:超时
WAIT_ABANDONED:
1: /*简单示例,一个线程不停读取用户输入并放入message列表, 2: 另一个线程模拟将message发送出去,如果没有消息,则发送线程处于阻塞状态等待, 3: 一旦有消息录入,输入线程将event置位,发送线程即被激活并逐个发送消息。*/ 4: #include "stdafx.h" 5: #include 6: #include 7: #include 8: #include 9: #include 10: using namespace std; 11: 12: #ifdef _UNICODE 13: typedef wstring tstring; 14: #define tcout wcout 15: #define tcin wcin 16: #else 17: typedef string tstring; 18: #define tcout cout 19: #define tcin cin 20: #endif /* _UNICODE */ 21: 22: typedef list StringList; 23: 24: HANDLE hMutex = NULL; 25: HANDLE hEvent = NULL; 26: HANDLE hSendThread = NULL; 27: StringList messages; 28: 29: bool isRunning; 30: 31: DWORD WINAPI SendThreadProc(LPVOID lpThreadParameter) 32: { 33: DWORD dw; 34: while(isRunning) 35: { 36: dw = WaitForSingleObject(hEvent, INFINITE); 37: if(dw != WAIT_OBJECT_0) 38: { 39: tcout > s; 78: if(s == _T("quit")) 79: { 80: isRunning = true; 81: break; 82: } 83: 84: DWORD dw = WaitForSingleObject(hMutex, INFINITE); 85: if(WAIT_OBJECT_0 != dw && WAIT_ABANDONED != dw) 86: { 87: tcout