关于多线程的超奇怪问题......

chxy85 2009-06-21 08:38:40
#include "stdafx.h"
#include "iostream.h"
#include "windows.h"

DWORD WINAPI thread(LPVOID p)
{
Sleep(1);
cout<<"123"<<endl;
return 0;
}
int main(int argc, char* argv[])
{
HANDLE aa;
for (int i = 0;i<3;i++)
{
aa = CreateThread(0,0,thread,"heihei",0,0);
CloseHandle(aa);
}
Sleep(1000);
return 0;
}


代码如上,很短,可是奇怪的是,为什么cout完全的次数和内容是不可预料的,有时候甚至程序会报错...如果注释掉//Sleep(1);输出多少正常点,但是cout次数还是有问题。
——求高手解答为什么会这样,若是创建多线程socket服务器,岂不是有很大的问题。
...全文
39 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
arong1234 2009-06-22
  • 打赏
  • 举报
回复
这样似乎没问题
[Quote=引用 12 楼 chxy85 的回复:]
十分感谢,我是这样想的,多个客户端连接到服务器,每个客户端连上服务器都有自己的一个socket和一个线程,那么采用文件读共享的模式读取文件并发送,每个线程有各自的文件发送的进度,这样会不会有问题?

[/Quote]
chxy85 2009-06-22
  • 打赏
  • 举报
回复
顶上去。。。顶上去...
yangs2000 2009-06-22
  • 打赏
  • 举报
回复
楼上说对了一半。临界区是保证了3个线程在输出的时候只有一个进程在工作。
其他进程等待.这样可以保证是顺序的3行123

但楼主说程序运行的时候有可能报错
如果没有临界区,输出结果因该是123数字各3个加3个回车。但是顺序不定。原因是因为windows的线程机制。

报错说明,还潜藏了一个问题。就是cout的<<重载不支持多线程。
cout的<<重载函数是在编译器的C运行时库里边。你需要换一个支持多线程的运行库。
对于VC来说是
项目-属性-c/c++-代码生成-运行库-:选多线程!(楼主用的是VC的话.我猜是6.0因为从03开始M$已经把不支持多线程的运行库去掉了)
chxy85 2009-06-22
  • 打赏
  • 举报
回复
还有就是即使去掉closehandle(),cout的次数也是不可预料的,有时会超过3个,如果我在for里面每个createthread后面都加个Sleep(10),输出则正常,说明必须等一个线程结束后,再启动一个才行,这样显然也不合适
chxy85 2009-06-22
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 arong1234 的回复:]

在使用共享资源(这里是标准输出流)时是不允许并行执行的,只要你使用共享资源,必然只有一个线程可以使用,其他线程都必须停下来等,你所理解的初衷是错误的
而你所谓的下载问题,如果是一个socket,多线程也是不允许的,只有你使用多个socket,才可能在多个线程中分别下载
这和closehandle没有任何关系。closehandle也不会结束线程
[/Quote]

十分感谢,我是这样想的,多个客户端连接到服务器,每个客户端连上服务器都有自己的一个socket和一个线程,那么采用文件读共享的模式读取文件并发送,每个线程有各自的文件发送的进度,这样会不会有问题?
wangcom 2009-06-22
  • 打赏
  • 举报
回复
应该这样

int main(int argc, char* argv[])
{
HANDLE aa;
for (int i = 0;i<3;i++)
{
aa = CreateThread(0,0,thread,"heihei",0,0);
if (aa!=INVALID_HANDLE_VALUE)
{
CloseHandle(aa);
}
}
Sleep(1000);
return 0;
}
dong364 2009-06-22
  • 打赏
  • 举报
回复
其实5楼已经说对了,只不过程序还得改点,献上:
#include "stdafx.h"
#include "iostream"
#include "windows.h"
using namespace std;

CRITICAL_SECTION cs;

DWORD WINAPI thread(LPVOID p)
{
EnterCriticalSection(&cs);

// Sleep(1);
cout<<"123"<<endl; // 外设的访问较慢

LeaveCriticalSection(&cs);

return 0;
}
int main(int argc, char* argv[])
{
HANDLE aa[3]={NULL};

InitializeCriticalSection(&cs);

for (int i = 0;i<3;i++)
{
aa[i] = CreateThread(0,0,thread,"heihei",0,0);
//CloseHandle(aa[i]);
}
//Sleep(1000);
WaitForMultipleObjects(3,aa,TRUE,INFINITE);
DeleteCriticalSection(&cs);
getchar();

return 0;
}
caonimarangwozhuce 2009-06-22
  • 打赏
  • 举报
回复
学习
chxy85 2009-06-22
  • 打赏
  • 举报
回复
顶上去,欢迎补充
arong1234 2009-06-22
  • 打赏
  • 举报
回复

在使用共享资源(这里是标准输出流)时是不允许并行执行的,只要你使用共享资源,必然只有一个线程可以使用,其他线程都必须停下来等,你所理解的初衷是错误的
而你所谓的下载问题,如果是一个socket,多线程也是不允许的,只有你使用多个socket,才可能在多个线程中分别下载
这和closehandle没有任何关系。closehandle也不会结束线程

arong1234 2009-06-22
  • 打赏
  • 举报
回复
在使用共享资源(这里是标准输出流)时允许并行执行的,只要你使用共享资源,必然只有一个线程可以使用,其他线程都必须停下来等,你所理解的初衷是错误的
而你所谓的下载问题,如果是一个socket,多线程也是不允许的,只有你使用多个socket,才可能在多个线程中分别下载
这和closehandle没有任何关系。closehandle也不会结束线程
[Quote=引用 7 楼 chxy85 的回复:]
谢谢LS几位,如果用临界区是没有问题,但是这不符合多线程同时执行的初衷了啊,试想如果建立一个socket文件下载服务器,总不能一个线程send结束后再启动另一个。

有的人说是CloseHandle()有问题,有可能线程还没有建立,就Close掉了,所以会报错,是这样吗?
[/Quote]
chxy85 2009-06-22
  • 打赏
  • 举报
回复
谢谢LS几位,如果用临界区是没有问题,但是这不符合多线程同时执行的初衷了啊,试想如果建立一个socket文件下载服务器,总不能一个线程send结束后再启动另一个。

有的人说是CloseHandle()有问题,有可能线程还没有建立,就Close掉了,所以会报错,是这样吗?
lijinfenghust 2009-06-21
  • 打赏
  • 举报
回复
多线程访问通常还要考虑同步和互斥问题。
cout打印到命令行属于对外设的操作,是非常慢的,因此,这段时间线程切换会影响打印结果,可以用临界区保护。

#include "stdafx.h"
#include "iostream.h"
#include "windows.h"

CRITICAL_SECTION CriticalSection;

DWORD WINAPI thread(LPVOID p)
{
EnterCriticalSection(&cs);
//Sleep(1);
cout<<"123"<<endl;
LeaveCriticalSection(&cs);
return 0;
}
int main(int argc, char* argv[])
{
InitializeCriticalSection(&cs);
HANDLE aa[3]={0};
for (int i = 0;i<3;i++)
{
aa[i] = CreateThread(0,0,thread,"heihei",0,0);
CloseHandle(aa);
}
Sleep(1000);
WaitForMultipleObjects(3,aa,TRUE,INFINITE);//等待直到子线程退出。
DeleteCriticalSection(&cs);
return 0;
}
wutaihua 2009-06-21
  • 打赏
  • 举报
回复
线程的资源分配并不是十分严格的,除非你在逻辑上进行了控制,不然任何不违背你编码逻辑的情况都不算做错误现象
chxy85 2009-06-21
  • 打赏
  • 举报
回复
顶上去
songtao_01 2009-06-21
  • 打赏
  • 举报
回复
cout输出是很慢的,而且你的多线程都是往一个地方输出,所以会出现你说的情况

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧