Window多线程同步之(互斥锁)
2017-12-22 14:41
155 查看
简述
互斥锁是用在多线程间对操作同一资源进行互斥的。一个线程占用了一个资源,那么别的线程就操作此资源,直到这个线程该释放互斥锁,其他的线程才开始可以重新抢夺这个互斥锁,成功获得互斥锁的线程利用这个资源,其他线程再次阻塞,周而复始。如对全局变量的访问,线程加锁后对变量进行读写操作,完成后释放互斥锁。比如多个线程对一个全局变量进行累加并打印。相关API
函数原型HANDLE WINAPI CreateMutexA(
_In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
_In_ BOOL bInitialOwner,
_In_opt_ LPCSTR lpName
);
lpMutexAttributes:表示安全控制,传入NULL
bInitialOwner: bool类型,传入true表示互斥量处于未触发状态,为创建线程拥有.
lpName:设置互斥量的名称
函数原型
WINBASEAPI DWORD WINAPI WaitForSingleObject(_In_ HANDLE hHandle, _In_ DWORD dwMilliseconds);
功能:获得互斥锁
hHandle:互斥量句柄
dwMilliseconds:等待时间,一般设为INFINITE,意为永久阻塞,直到获得互斥量。
函数原型
WINBASEAPI BOOL WINAPI ReleaseMutex(_In_ HANDLE hMutex);
功能:释放互斥锁
参数:hMutex:互斥量句柄
源码
//共享资源 static int num = 0; //子线程函数 unsigned int __stdcall ChildThreadFunc(LPVOID pM) { while (true) { Sleep(500); num++; printf("num:%d\n", num); } return 0; } int main() { HANDLE handle[5] = { 0 }; for (int i = 0; i < 5; i++) { handle[i] = (HANDLE)_beginthreadex(NULL, 0, ChildThreadFunc, NULL, 0, NULL); } //阻塞等待 for (int i = 0; i < 5; i++) { WaitForSingleObject(handle[i], -1); } printf("主线程 num:%d\n", num); getchar(); return 0; }
结果
这是在没有添加互斥锁的情况下得到的结果,显然是错误的,我们想要的结果的应该是1,2,3,4...
错误原因分析:
1,在这段代码中子线程函数会对全局变量num进行写(num++)和读(printf)两个操作,这两个步骤有可能被打断,即但线程1对num进行写(num++)操作完后还未读时,它就失去了cpu时间碎片,线程1被挂起。这时线程2抢到了cpu时间碎片并对num进行写(num++)操作,这样num进行了两次++操作,当线程1再次获得cpu时间碎片并读(printf)取数据时就会发送错误。
2,"num++;"这个语句也不是原子操作,它分为三步走。换句话说就是他也有可能被打断,也会发生上面的错误。
第一步将num的值从内存中读取到寄存器eax中。
第二步将寄存器eax中的值与1相加,计算结果仍存入寄存器eax中。
第三步将寄存器eax中的值写回内存中。
解决思路:
只要保证线程对共享资源的操作是不会被打断的,即当一个线程对这个资源进行读写操作时,其他线程就不能对此资源操作。声明一个全局互斥锁,并初始化。在线程对共享资源操作开始时加锁,操作完成后释放即可。
正确方法
源码//共享资源 static int num = 0; //互斥锁 HANDLE g_Mutex = CreateMutex(NULL, FALSE, NULL); //子线程函数 unsigned int __stdcall ChildThreadFunc(LPVOID pM) { while (true) { Sleep(500); WaitForSingleObject(g_Mutex, INFINITE);//等待互斥量 num++; printf("num:%d\n", num); ReleaseMutex(g_Mutex); } return 0; } int main() { HANDLE handle[5] = { 0 }; for (int i = 0; i < 5; i++) { handle[i] = (HANDLE)_beginthreadex(NULL, 0, ChildThreadFunc, NULL, 0, NULL); } //阻塞等待 for (int i = 0; i < 5; i++) { WaitForSingleObject(handle[i], -1); } printf("主线程 num:%d\n", num); getchar(); return 0; }
结果
相关文章推荐
- NET多线程同步方法详解(二):互斥锁(lock)
- Window多线程同步(事件)
- Linux多线程同步——互斥锁
- NET多线程同步方法详解(二):互斥锁(lock) 收藏
- 多线程同步(信号量,互斥锁,条件变量)
- 多线程同步之互斥锁
- Window进程内多线程同步
- win32进阶必备:多线程同步之互斥锁
- Pthread线程 —— 多线程同步 互斥锁(mutex)
- .NET多线程同步方法详解(二):互斥锁(lock)
- NET多线程同步方法:互斥锁(Lock)
- C++11 多线程同步 互斥锁 条件变量
- window 互斥锁
- window 7英文版转化为中文版
- adbpush.bat (window batch file)
- 从Empty Application到Window Based Application
- android PopWindow
- js onclick跳转页面方法(window.open)
- Android 价值千万java多线程同步 <四> synchronized&Lock&Atomic6种方式
- window.showModalDialog关闭子页面刷新父页面