线程就是让程序有多个入口点,进程不执行代码,是线程的容器,线程都共享进程的地址空间、对象句柄、代码和数据等其他资源,操作系统为每一个运行线程安排一定的CPU时间
线程
就是让程序有多个入口点,进程不执行代码,是线程的容器。
线程都共享进程的地址空间、对象句柄、代码和数据等其他资源。
操作系统为每一个运行线程安排一定的CPU时间
GetCurrentThreadId()获取当前线程id
创建线程简单的小例子
GetCurrentThreadId()获取当前线程id
创建线程简单的小例子
CreateThread/_beginthreadex 创建线程
ExitThread/_endthreadex 退出线程
SuspendThread 挂起线程
ResumeThread 恢复线程
TerminateThread 终止线程
GetCurrentThread 获取当前线程句柄(伪)
GetCurrentThreadId 获取当前线程ID
GetExitCodeThread 获取线程退出码
同步
线程同步问题
不同线程使用同一变量
因为看汇编的话nCount++,分为三条指令
1.把数据放入ECX寄存器中
2.ECX数据加1
3.写入内存
所以线程切换的时候可能取出的是同一个nCount的值,再加一的话就等于加了一次而不是两次。这里就用到了线程同步的原理,把需要的操作的代码编程原子,要么不执行,要么执行完。
自旋锁
这样就不会发生之前的情况
对于这些原子操作的函数还有许多有加1、减一、交换指针等
那么如果有一段代码需要原子操作怎么办,我们可以使用上面的原子操作给他上锁
临界区
// Global variable CRITICAL_SECTION CriticalSection; void main() { ... // Initialize the critical section one time only. InitializeCriticalSection(&CriticalSection); ... // Release resources used by the critical section object. DeleteCriticalSection(&CriticalSection) } DWORD WINAPI ThreadProc( LPVOID lpParameter ) { ... // Request ownership of the critical section. __try { EnterCriticalSection(&CriticalSection); // Access the shared resource. } __finally { // Release ownership of the critical section. LeaveCriticalSection(&CriticalSection); } }
CreateEvent
可以防多开,检测event的内核名
配合WaitforSingalObject,可以同步进程的代码执行
跨进程使用句柄
内核对象取名字
父子继承
复制句柄
BOOL DuplicateHandle( HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions );
信号灯和线程池
#pragma once #include <windows.h> #include <queue> #include <string> #include <mutex> #include <sstream> using namespace std; class CMyThreadPool { public: CMyThreadPool(); ~CMyThreadPool(); bool Create() { //创建一个信号灯/信号量 m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL); for (int i = 0; i < 4; i++) { m_hThreadAry[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, this, 0, NULL); } return true; } bool Destroy() { //CloseHandle(m_hSem); WaitForMultipleObjects(4, m_hThreadAry, TRUE, INFINITE); return true; } void addTask(string str) { m_mutex.lock(); m_TaskQue.push(str); m_mutex.unlock(); ReleaseSemaphore(m_hSem, 1, NULL); } string getTask() { lock_guard<mutex> guard(m_mutex); if (m_TaskQue.size() == 0) { return ""; } string str = m_TaskQue.front(); m_TaskQue.pop(); return str; } HANDLE m_hThreadAry[4]; queue<string> m_TaskQue; mutex m_mutex; HANDLE m_hSem; }; DWORD ThreadFunc(LPVOID lpParam) { CMyThreadPool* pThis = (CMyThreadPool*)lpParam; int nThreadID = GetCurrentThreadId(); while (WaitForSingleObject(pThis->m_hSem, INFINITE) == WAIT_OBJECT_0) { //取任务,并执行 string str = pThis->getTask(); if (!str.empty()) { stringstream sStr; sStr << nThreadID << ": " <<str.c_str(); OutputDebugStringA(sStr.str().c_str()); } } return 0; }
#include "stdafx.h" #include <windows.h> #include "MyThreadPool.h" int main() { CMyThreadPool pool; pool.Create(); char buffer[20] = {0}; for (int i = 0; i < 1000; i++) { memset(buffer, 0, 20); _itoa_s(i, buffer, 10); pool.addTask(buffer); } pool.Destroy(); return 0; }
转载请说明出处
草堂教程网 » Windows编程中的进程线程同步
草堂教程网 » Windows编程中的进程线程同步