C++多线程重点难点(二)理解
来源:互联网 发布:知乎文章怎么复制 编辑:程序博客网 时间:2024/06/14 08:09
先上图:
分析下这个问题的考察点,主要考察点有二个:
1.主线程创建子线程并传入一个指向变量地址的指针作参数,由于线程启动须要花费一定的时间,所以在子线程根据这个指针访问并保存数据前,主线程应等待子线程保存完毕后才能改动该参数并启动下一个线程。这涉及到主线程与子线程之间的同步。
2.子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。这涉及到各子线程间的互斥。
直接上代码:
//经典线程同步互斥问题#include <stdio.h>#include <process.h>#include <windows.h>long g_nNum; //全局资源unsigned int __stdcall Fun(void *pPM); //线程函数const int THREAD_NUM = 10; //子线程个数int main(){ g_nNum = 0; HANDLE handle[THREAD_NUM]; int i = 0; while (i < THREAD_NUM) { handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL); i++;//等子线程接收到参数时主线程可能改变了这个i的值 } //保证子线程已全部运行结束 WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); return 0;}unsigned int __stdcall Fun(void *pPM){//由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来 int nThreadNum = *(int *)pPM; //子线程获取参数 Sleep(50);//some work should to do g_nNum++; //处理全局资源 Sleep(0);//some work should to do printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum); return 0;}
这是一个既不互斥也不同步的程序,现在要求如下:
1.子线程输出的线程序号不能重复
2.全局变量的输出必须递增
下面这段代码是我通过原理进行修改的,实现了上面的要求,但是并没有实现同步,可以加深理解:
#include <stdio.h>#include <process.h>#include <windows.h>#include <iostream>using namespace std;volatile long g_nNum; //全局资源unsigned int __stdcall Fun(void *pPM); const int THREAD_NUM = 10; //子线程个数int main(){ g_nNum = 0; HANDLE handle[THREAD_NUM]; int cas = 10; while (cas--){ int i = 0; while (i < THREAD_NUM) { Sleep(1);//***延迟下一个子进程创建,就可以保证前一子进程完成保存和输出操作 handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL); i++;//***等子线程接收到参数时主线程可能改变了这个i的值 } //保证子线程已全部运行结束 WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); cout << "case: " << cas << "全局: " << g_nNum << endl; } return 0;}unsigned int __stdcall Fun(void *pPM){ //由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来 long nThreadNum = *(long *)pPM; //子线程获取参数 Sleep(5); g_nNum++; //处理全局资源 //InterlockedIncrement((LPLONG)&g_nNum);//这里采用原子操作但似乎不影响结果 Sleep(0);//some work should to do printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum);//第一个元素是i,第二个元素是全局变量 return 0;}
实现多线程同步的方法有:关键段(临界区),互斥量,信号量,事件等
更详细的可以去看:http://blog.csdn.net/morewindows/article/details/7442333
值得注意的是:
- 当在同一进程中的多线程同步时,临界区是效率最最高,基本不需要什么开销。而内核对象由于要进行用户态和内核态的切换,开销较大,但是内核对象由于可以命名,因此它们同时可以用于进程间的同步。另外,值得一提的是,信号量可以设置允许访问资源的线程或进程个数,而不仅仅是只允许单个线程或进程访问资源。
- 信号量的使用特点使其更适用于对Socket(套接字)程序中线程的同步。例如,网络上的HTTP服务器要对同一时间内访问同一页面的用户数加以限制,这时可以为每一个用户对服务器的页面请求设置一个线程,而页面则是待保护的共享资源,通过使用信号量对线程的同步作用可以确保在任一时刻无论有多少用户对某一页面进行访问,只有不大于设定的最大用户数目的线程能够进行访问,而其他的访问企图则被挂起,只有在有用户退出对此页面的访问后才有可能进入。
- 虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。
- 尽量避免用户态与内核态的切换
阅读全文
0 0
- C++多线程重点难点(二)理解
- c++多线程重点难点(三)Mutex
- c++多线程重点难点(四)semaphore
- c++多线程重点难点(五)Event
- Spark重点难点知识总结(二)
- c++多线程重点难点(一)interlocked系列原子操作
- c++多线程重点难点(六)CriticalSection
- C# 多线程(二)
- [多线程]GCD深入理解(二)
- Linux C 多线程编程学习(二)
- C#.net 多线程编程(二)
- linux c 多线程编程练习(二)
- Objective-C Runtime深入理解(二)
- 深入理解C语言指针(二)
- C语言指针理解(二)
- Spark重点难点知识总结(一)
- JAVA笔记:多线程的理解及应用(二)
- ios开发关于多线程编程的理解(二)
- Oracle手动固定SQL执行计划
- HDU
- Android开发丶解决应用不能在Android7.0+设备上不能安装的问题
- Python入门级--__mian__关键字
- Electron中使用JQuery
- C++多线程重点难点(二)理解
- 如何创建JAVA项目
- WebUploader 设置原图上传,不启用压缩
- 在Xcode中制作.a文件
- Android 常用开发功能 博客导航
- 51Nod 1134 最长递增子序列(二分/lower_bound)
- .NET使用NPOI读取Word模板并替换关键字并下载
- poj 3723 最大权森林问题
- 【软考之旅】第一章 数据结构与算法