线程创建后,未必立即运行
来源:互联网 发布:apache kylin教程 编辑:程序博客网 时间:2024/05/22 06:34
线程创建,并不立即执行,而是等时间片到来后再执行。
一个进程,包含多个线程。
则这个线程共享进程的数据等资源,各个线程呈现并发执行状态。
线程执行时,所传入的参数值是执行时才传入的,而不是创建线程时传入的。
考虑以下程序:
#include "stdafx.h"#include <iostream>#include <Windows.h>#include <process.h>using namespace std;long g_nNum;unsigned int _stdcall ThreadFun(void *pPM);const int THREAD_NUM=10;CRITICAL_SECTION g_csThreadCore;HANDLE hSemaphore;
int main(array<System::String ^> ^args){g_nNum=0;HANDLE handle[10];int i=0;//初始化关键段InitializeCriticalSection(&g_csThreadCore);//创建信号量hSemaphore=CreateSemaphore(NULL,0,1,NULL);while(i<THREAD_NUM){handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);//WaitForSingleObject(hSemaphore,INFINITE);i++;}WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);DeleteCriticalSection(&g_csThreadCore);CloseHandle(hSemaphore); cin>>i; return 0;}unsigned int _stdcall ThreadFun(void *pPM){int nThreadnum=*(int*)pPM;ReleaseSemaphore(hSemaphore,1,NULL);//Sleep(50);EnterCriticalSection(&g_csThreadCore);g_nNum++;//Sleep(50);printf("线程编号为%d 全局资源值为%d\n",nThreadnum,g_nNum);LeaveCriticalSection(&g_csThreadCore);return 0;}
运行结果:
线程编号为7 全局资源值为1
线程编号为7 全局资源值为2
线程编号为8 全局资源值为3
线程编号为7 全局资源值为4
线程编号为7 全局资源值为5
线程编号为7 全局资源值为6
线程编号为10 全局资源值为7
线程编号为10 全局资源值为8
线程编号为7 全局资源值为9
线程编号为7 全局资源值为10
由此可见,线程编号不正确,原因是:
创建线程后,不立即执行, 当执行时,传入参数的值已经改变。
而且,线程编号有重复值, 这说明在i值改变前,启动了好几个线程, 传入这些线程的值都是i(编号),因此才会出现线程编号重复问题。
比如: i==0时,创建线程0
i==1时,创建线程1
i==2时,创建线程2
但,此时还没有一个线程执行,当i=3时,创建线程3,
此时,时间片轮到线程了,因此可能线程0开始执行,但执行线程0时,传入的为当前i的值3, 因此线程0的编号被误改为3,这个线程未执行完,又启动了其他线程,比如线程1,但线程1传入的参数也是i的当前值3
如何才能让线程编号正确?
之所以不正确显示,是因为线程执行时,未能传入正确的i值。
因此,如果线程创建成功执行时,能传入正确值的话,这个问题就解决了。
怎样传入正确值呢?
handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);
i++;
创建线程i,此线程创建后,并没有立即执行,而是直接i++ 然后创建另一个线程。
如果在i++之前,能确保此线程执行的话,则能传入正确的i值。。。。
handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);
WaitForSingleObject(hSemaphore,INFINITE);
i++;
WaitForSingleObject(hSemaphore,INFINITE);
直到hSemaphore有信号时,才往下继续执行,而只有当创建的线程执行时,Semaphore才有信号。
因为线程函数中有 设置信号的函数: ReleaseSemaphore(hSemaphore,1,NULL);
这样就保证了线程编号的正确。
int main(array<System::String ^> ^args){g_nNum=0;HANDLE handle[10];int i=0;//初始化关键段InitializeCriticalSection(&g_csThreadCore);//创建信号量hSemaphore=CreateSemaphore(NULL,0,1,NULL);while(i<THREAD_NUM){handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);WaitForSingleObject(hSemaphore,INFINITE);i++;}WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);DeleteCriticalSection(&g_csThreadCore);CloseHandle(hSemaphore); cin>>i; return 0;}
线程编号为0 全局资源值为1
线程编号为1 全局资源值为2
线程编号为2 全局资源值为3
线程编号为3 全局资源值为4
线程编号为4 全局资源值为5
线程编号为5 全局资源值为6
线程编号为6 全局资源值为7
线程编号为7 全局资源值为8
线程编号为8 全局资源值为9
线程编号为9 全局资源值为10
注意:线程函数除设置信号量外,还设置了临界区,临界区至多只有一个线程访问。
当一个线程进入临界区后,其它线程只能等待它退出临界区后,再访问。
这保证了,临界区内的全局数据不被多个线程同时修改,保证了临界区内的程序顺序执行
EnterCriticalSection(&g_csThreadCore);g_nNum++;printf("线程编号为%d 全局资源值为%d\n",nThreadnum,g_nNum);LeaveCriticalSection(&g_csThreadCore);
假如: 去掉临界区
线程编号为3 全局资源值为4
线程编号为2 全局资源值为1
线程编号为0 全局资源值为2
线程编号为1 全局资源值为3
线程编号为8 全局资源值为5
线程编号为9 全局资源值为6
线程编号为5 全局资源值为8
线程编号为7 全局资源值为10
线程编号为6 全局资源值为7
线程编号为4 全局资源值为9
由此可见,全局资源顺序有误,甚至会有重复现象
这是因为:各个线程 同时访问全局变量,所导致的不一致
参考资料:http://blog.sina.com.cn/s/blog_6120646301012szj.html
- 线程创建后,未必立即运行
- CreateThread后立即CloseHandle,为什么线程还在运行?
- 【技巧点滴】线程创建后需要立即调用CloseHandle
- 创建线程后为什么关闭了线程句柄,线程还是可以运行?
- 创建线程后为什么关闭了线程句柄,线程还是可以运行?
- 创建线程后为什么关闭了线程句柄,线程还是可以运行?
- 创建线程后为什么关闭了线程句柄,线程还是可以运行?
- 创建线程后为什么关闭了线程句柄,线程还是可以运行?
- 集成FUSE的程序在后台运行后,创建的多个线程被自动杀死!
- java创建运行线程Thread
- 线程的创建和运行
- 线程的创建及运行
- 关于立即运行函数
- 线程管理之线程创建和运行
- Quartz 定时器动态创建任务和修改执行时间修改后出现立即执行情况
- 用[@[] mutableCopy]创建NSMutableArray,但未必好
- Docker 运行Ubuntu 立即退出
- 更改注册表后立即生效
- Verilog HDL 测量输入信号的正、负脉宽
- 编码20年的老程序员分享所积累的20条编程经验
- 正则表达式30分钟入门教程 版本:v2.3 (2008-4-13) 作者:deerchao
- 非printf形式打印各种数据类型的十六进制和二进制
- 以Webkit为核心的浏览器的CSS样式-----Mask
- 线程创建后,未必立即运行
- DM8168 EMAC/MDIO模块(5)
- 浅析Android下的Android.mk文件
- 如何理解数据结构中的引用参数(&)
- php中的json
- Activity栈(收藏)
- 趣题2:火柴游戏
- 每个程序员都应读的书
- 人生大器