线程学习总结-----/*自己编写*/
来源:互联网 发布:网络扁平化的优点 编辑:程序博客网 时间:2024/06/01 20:50
一、 WaitForSingleObject()函数
二、 _beginthreadex()和CreatThread()区别
使用标准C运行库函数是,尽量使用_beginthreadex()函数。
参考:http://blog.csdn.net/morewindows/article/details/7421759
三、 Interlocked系列函数
多线程环境下对一个全局变量进行读写时,对这个变量的操作必须是原子操作,即一个线程对其进行访问修改时,其它线程要等这个线程操作完毕后才能进行修改。对变量进行原子操作可使用interlocked系列函数,包括自增、自减、赋值等操作。
参考:http://blog.csdn.net/morewindows/article/details/7429155
四、同步与互斥:
同步:主线程等待子线程某个操作完成后再启动下一个动作,这就涉及到线程间的同步;
互斥:子线程之间会互斥的改动和输出全局变量,而要求全局变量规律的改变,这就涉及到线程间的互斥。
参考:http://blog.csdn.net/morewindows/article/details/7442639
http://blog.csdn.net/morewindows/article/details/7445233
解决互斥可以使用interlocked系列函数、也可以使用关键段。
但这两个都解决不了同步问题,同步可以通过事件来完成。
如果线程间的互斥只涉及到一个全局变量,可以通过Interlocked系列函数来解决;如果线程间的互斥是一段操作,则需要使用关键段来解决。
例:参考中的经典多线程例子里,线程函数如下:
//子线程函数 unsigned int __stdcall Fun(void *pPM) { int nThreadNum = *(int *)pPM; SetEvent(g_hThreadEvent);Sleep(50);//some work should to do EnterCriticalSection(&g_csThreadCode);//进入各子线程互斥区域 g_nNum++; Sleep(0);//some work should to do printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum); LeaveCriticalSection(&g_csThreadCode);//离开各子线程互斥区域 return 0; }
主函数如下:
// MulThread.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <stdio.h>#include <Windows.h>#include <process.h>long g_nNum; //全局资源 unsigned int __stdcall Fun(void *pPM); //线程函数 const int THREAD_NUM = 10; //子线程个数 //关键段变量声明 CRITICAL_SECTION g_csThreadCode; HANDLE g_hThreadEvent; int _tmain(int argc, _TCHAR* argv[]){printf(" 经典线程同步 关键段\n"); printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n"); //关键段初始化 InitializeCriticalSection(&g_csThreadCode); g_hThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);HANDLE handle[THREAD_NUM]; g_nNum = 0; int i = 0; while (i < THREAD_NUM) { handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL); WaitForSingleObject(g_hThreadEvent,INFINITE);i++; } WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); DeleteCriticalSection(&g_csThreadCode); CloseHandle(g_hThreadEvent);system("pause");return 0;}
如果,不需要输出printf这句,直接用interlocked函数InterlockedIncrement((LPLONG)&g_nNum),代替g_nNum++即可解决互斥问题。但要求是要有输出这句,printf语句中因又用到了g_nNum这个全局变量,所以如果只是用Interlocked函数,
//子线程函数 unsigned int __stdcall Fun(void *pPM) { int nThreadNum = *(int *)pPM; SetEvent(g_hThreadEvent);Sleep(50);//some work should to do //EnterCriticalSection(&g_csThreadCode);//进入各子线程互斥区域 //g_nNum++; InterlockedIncrement((LPLONG)&g_nNum);Sleep(0);//some work should to do printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum); //LeaveCriticalSection(&g_csThreadCode);//离开各子线程互斥区域 return 0; }
输出结果如下:
可以看到,全局变量的输出值并没有依次递增,这是因为printf这句并不是紧接在InterlockedIncrement((LPLONG)&g_nNum)后执行,比如线程3执行完InterlockedIncrement((LPLONG)&g_nNum)后,还没执行后面的printf,线程5开始调用Fun,进入到printf这句,此时的g_nNum仍存在互斥。
为解决此问题,应用关键段,将有互斥的语句全包含进来,这样可以解决互斥问题。
如下:
EnterCriticalSection(&g_csThreadCode);//进入各子线程互斥区域 g_nNum++; Sleep(0);//some work should to do printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum); LeaveCriticalSection(&g_csThreadCode);//离开各子线程互斥区域线程函数按上述修改后,输出如下:
总结:
单个全局变量的互斥可使用Interlocked系列函数完成原子操作,一段互斥的操作可使用关键段;
关键段是有“线程所有权”概念的;
关键段可以用于线程间的互斥,但不可以用于同步;
事件可以解决线程间同步问题,因此也能解决互斥问题。
五、 互斥量
互斥量是内核对象,它与关键段都有“线程所有权”所以不能用于线程的同步。
互斥量能够用于多个进程之间线程互斥问题,并且能完美的解决某进程意外终止所造成的“遗弃”问题。
参考:http://blog.csdn.net/morewindows/article/details/7470936
- 线程学习总结-----/*自己编写*/
- android学习总结四:如何编写自己的Android.mk
- javaweb学习总结——编写自己的JDBC框架
- java web学习总结40:编写自己的JDBC框架
- java线程学习(五)—java内存模型自己总结
- java线程学习(五)—java内存模型自己总结
- QT 使用总结 -----/* 自己编写 */
- QT SQL总结-----/*自己编写*/
- C51技巧总结-----/*自己编写*/
- 利用Java编写自己的线程池
- 自己编写的简单的线程池
- java线程池---编写自己的线程池
- javaweb学习总结(四十)——编写自己的JDBC框架
- javaweb学习总结(四十)——编写自己的JDBC框架
- javaweb学习总结(四十)——编写自己的JDBC框架
- javaweb学习总结(四十)——编写自己的JDBC框架
- javaweb学习总结(四十)——编写自己的JDBC框架
- JavaWeb学习总结(四十)——编写自己的JDBC框架
- react native ios添加ART.xcodeproj(ReactNative No component found for view with name “ARTSurfaceView”)
- Android图形合成和显示系统---基于高通MSM8k MDP4平台
- caffe 命令及参数解析
- java、八大经典书籍,你看过几本?
- 基于《Selenium 2自动化测试实战》的学习笔记(1)—— 软件测试分类
- 线程学习总结-----/*自己编写*/
- Jquery 表单校验注册+购物车
- mongodb 访问权限控制
- 账号已被停用,请咨询系统管理员
- 剑指offer 40. 数组中只出现一次的数字
- [android]Gradle 应用插件︰ com.google.gms.google 服务
- [C++]bitset类用法
- 数据库链接错误,有可能不是用户名密码的问题
- 最全的Java笔试题库之选择题篇-总共234道【181~234】