C++线程同步

来源:互联网 发布:表格如何筛选重复数据 编辑:程序博客网 时间:2024/05/18 17:25
线程的同步分 <用户模式的线程同步>和<内核对象的线程同步>两类


用户模式中线程的同步方法主要有原子访问和临界区等方法。特点是同步速度特别快,适合于对线程运行速度有严格要求的场合。
内核对象的线程同步则主要由事件、等待定时器、信号量以及信号灯等内核对象构成。由于这种同步机制使用了内核对象,使用时必须将线程从用户模式切换到内核模式,因此同步速度较慢,但在适用性上却要远优于用户模式的线程同步方式。


事件对象在线程退出时不会自动释放锁
互斥对象在线程退出时会自动释放锁

信号量暂不讨论


互斥对象:

// ThreadTest.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "ThreadTest.h"#include <afxmt.h>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCWinApp theApp;using namespace std;// 互斥对象 HANDLE hMutex = NULL;// 共享资源 char g_cArray[10] = {0};UINT ThreadProc1(LPVOID lParamter){while (true){// 等待互斥对象通知WaitForSingleObject(hMutex, INFINITE);// 对共享资源进行写入操作printf("thread1 is running\n");//break; 如果线程意外中止,系统会自动释放互斥对象// 释放互斥对象ReleaseMutex(hMutex);Sleep(1000);}printf("thread1 exit\n");return 0;}UINT ThreadProc2(LPVOID lParamter){while (true){// 等待互斥对象通知WaitForSingleObject(hMutex, INFINITE);// 对共享资源进行写入操作printf("thread2 is running\n");// 释放互斥对象ReleaseMutex(hMutex);Sleep(1000);}printf("thread2 exit\n");return 0;}int MyEntry(){hMutex = CreateMutex(NULL, FALSE, NULL);// 启动线程AfxBeginThread(ThreadProc1, NULL);AfxBeginThread(ThreadProc2, NULL);// 等待计算完毕Sleep(INFINITE);return 0;}int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){int nRetCode = 0;if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){cerr << _T("Fatal Error: MFC initialization failed") << endl;nRetCode = 1;}else{return MyEntry();}return nRetCode;}


互斥对象_MFC:

// ThreadTest.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "ThreadTest.h"#include <afxmt.h>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCWinApp theApp;using namespace std;// MFC互斥类对象 CMutex g_clsMutex(FALSE, NULL);// 共享资源 char g_cArray[10] = {0};UINT ThreadProc1(LPVOID lParamter){while (true){// 等待互斥对象通知g_clsMutex.Lock();// 对共享资源进行写入操作printf("thread1 is running\n");//break; 如果线程意外中止,系统会自动释放互斥对象// 释放互斥对象g_clsMutex.Unlock();Sleep(1000);}printf("thread1 exit\n");return 0;}UINT ThreadProc2(LPVOID lParamter){while (true){// 等待互斥对象通知g_clsMutex.Lock();// 对共享资源进行写入操作printf("thread2 is running\n");//如果线程意外中止,系统会自动释放互斥对象//break; // 释放互斥对象g_clsMutex.Unlock();Sleep(1000);}printf("thread2 exit\n");return 0;}int MyEntry(){// 启动线程AfxBeginThread(ThreadProc1, NULL);AfxBeginThread(ThreadProc2, NULL);// 等待计算完毕Sleep(INFINITE);return 0;}int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){int nRetCode = 0;if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){cerr << _T("Fatal Error: MFC initialization failed") << endl;nRetCode = 1;}else{return MyEntry();}return nRetCode;}


临界区:

// ThreadTest.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "ThreadTest.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCWinApp theApp;using namespace std;// 虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。// 临界区结构对象 CRITICAL_SECTION g_cs;// 共享资源 char g_cArray[10];DWORD WINAPI ThreadProc1(LPVOID lParamter){// 可以通过添加结构化异常处理代码来确保LeaveCriticalSection()语句的执行// 进入临界区EnterCriticalSection(&g_cs);// 对共享资源进行写入操作for (int i = 0; i < 10; i++){g_cArray[i] = 'a';Sleep(1);}// 离开临界区LeaveCriticalSection(&g_cs);return 0;}DWORD WINAPI ThreadProc2(LPVOID lParamter){// 进入临界区EnterCriticalSection(&g_cs);// 对共享资源进行写入操作for (int i = 0; i < 10; i++){g_cArray[10 - i - 1] = 'b';Sleep(100);}// 离开临界区LeaveCriticalSection(&g_cs);return 0;}int MyEntry(){// 必须初始化临界区InitializeCriticalSection(&g_cs);// 启动线程HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);HANDLE hThread2 = ::CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);::CloseHandle(hThread1);::CloseHandle(hThread2);// 等待计算完毕Sleep(1000);// 结果::MessageBox(NULL, g_cArray, _T("共享资源结果:"), MB_ICONINFORMATION);return 0;}int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){int nRetCode = 0;if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){cerr << _T("Fatal Error: MFC initialization failed") << endl;nRetCode = 1;}else{return MyEntry();}return nRetCode;}


临界区_MFC:

// ThreadTest.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "ThreadTest.h"#include <afxmt.h>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCWinApp theApp;using namespace std;// MFC临界区结构对象 CCriticalSection g_clsCriticalSection;// 共享资源 char g_cArray[10];UINT ThreadProc1(LPVOID lParamter){// 进入临界区g_clsCriticalSection.Lock();// 对共享资源进行写入操作for (int i = 0; i < 10; i++){g_cArray[i] = 'a';Sleep(10);}// 离开临界区g_clsCriticalSection.Unlock();return 0;}UINT ThreadProc2(LPVOID lParamter){// 进入临界区g_clsCriticalSection.Lock();// 对共享资源进行写入操作for (int i = 0; i < 10; i++){g_cArray[10 - i - 1] = 'b';Sleep(150);}// 离开临界区g_clsCriticalSection.Unlock();return 0;}int MyEntry(){// 启动线程AfxBeginThread(ThreadProc1, NULL);AfxBeginThread(ThreadProc2, NULL);// 等待计算完毕Sleep(1000);// 报告计算结果CString sResult(g_cArray);AfxMessageBox(sResult);return 0;}int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){int nRetCode = 0;if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){cerr << _T("Fatal Error: MFC initialization failed") << endl;nRetCode = 1;}else{return MyEntry();}return nRetCode;}

事件对象:

// ThreadTest.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "ThreadTest.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCWinApp theApp;using namespace std;// 事件句柄 HANDLE hEvent = NULL;// 共享资源 char g_cArray[10];UINT ThreadProc1(LPVOID lParamter){while (true){// 等待事件置位WaitForSingleObject(hEvent, INFINITE);// 对共享资源进行写入操作printf("thread1 is running\n");// 处理完成后即将事件对象置位SetEvent(hEvent);Sleep(2000);}printf("thread1 exit\n");return 0;}UINT ThreadProc2(LPVOID lParamter){while (true){// 等待事件置位WaitForSingleObject(hEvent, INFINITE);// 对共享资源进行写入操作printf("thread2 is running\n");// 处理完成后即将事件对象置位SetEvent(hEvent);Sleep(1000);}return 0;}int MyEntry(){/*HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性BOOL bManualReset, // 复位方式.BOOL bInitialState, // 初始状态.为TRUE时,其它线程可获取hEvent,否则要等待到有信号时LPCTSTR lpName // 对象名称);*/// 创建事件hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);// 事件置位//SetEvent(hEvent);// 启动线程AfxBeginThread(ThreadProc1, NULL);AfxBeginThread(ThreadProc2, NULL);// 等待计算完毕Sleep(INFINITE);CloseHandle(hEvent);return 0;}int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){int nRetCode = 0;if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){cerr << _T("Fatal Error: MFC initialization failed") << endl;nRetCode = 1;}else{return MyEntry();}return nRetCode;}

事件对象_MFC:

// ThreadTest.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "ThreadTest.h"#include <afxmt.h>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCWinApp theApp;using namespace std;// MFC事件类对象CEvent g_clsEvent(FALSE, FALSE, NULL, NULL);// 共享资源 char g_cArray[10] = {0};UINT ThreadProc1(LPVOID lParamter){while (true){// 等待锁,直到得到锁g_clsEvent.Lock();// 对共享资源进行写入操作printf("thread1 is running\n");// 处理完成后即将事件对象置位g_clsEvent.SetEvent();Sleep(1000);}printf("thread1 exit\n");return 0;}UINT ThreadProc2(LPVOID lParamter){while (true){// 等待锁,直到得到锁g_clsEvent.Lock();// 对共享资源进行写入操作printf("thread2 is running\n");// 处理完成后即将事件对象置位g_clsEvent.SetEvent();Sleep(1000);}g_clsEvent.Unlock();printf("thread2 exit\n");return 0;}int MyEntry(){// 事件置位SetEvent(g_clsEvent);// 启动线程AfxBeginThread(ThreadProc1, NULL);AfxBeginThread(ThreadProc2, NULL);// 等待计算完毕Sleep(INFINITE);return 0;}int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){int nRetCode = 0;if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){cerr << _T("Fatal Error: MFC initialization failed") << endl;nRetCode = 1;}else{return MyEntry();}return nRetCode;}


原创粉丝点击