有关多线程的疑问?

papaofdoudou
新星创作者: 人工智能技术领域
领域专家: 嵌入式与硬件开发技术领域
2009-06-04 08:23:13
请看代码
#include <iostream.h>
#include <windows.h>


DWORD WINAPI Fun1Proc(LPVOID lpParameter);


void main()
{
HANDLE hThread1,hThread2,hThread3;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread3=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
//创建的三个线程利用的都是同一个线程函数,竟然不报错,为什么?
CloseHandle(hThread1);
CloseHandle(hThread2);
CloseHandle(hThread3);
while(1)
{

cout<<"main thread is running"<<endl;
}
}


DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
int i=0;
while(1)
{
i++; //每个线程利用的都是同一个i吗?如果不是,三个线程的代码区都是一样的,执行的都是同一段代码,那么这个i存放在什么地方??
cout<<"i="<<i<<endl; //这些i之间如何做到线程间的同步??
}
return 0;
}
对线程和设计到操作系统的问题知之甚少,还望各位朋友指点一二!
万分感激!
...全文
139 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiejhzwrgcky 2009-06-06
  • 打赏
  • 举报
回复
顶下
appleshao 2009-06-06
  • 打赏
  • 举报
回复
CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);

这个函数可以不返回uid吗?
T技术沙龙 2009-06-06
  • 打赏
  • 举报
回复
学习,谢谢
DreamFreeLancer 2009-06-06
  • 打赏
  • 举报
回复
LZ确实对线程知之甚少,线程是一个系统运行期概念,属于软件系统中的动态结构,而线程函数只是定义线程行为,属软件系统中的静态结构。函数中所有的栈变量都将是线程独立的,你就是用同一线程函数创建一千个线程也没有问题。
cheifer 2009-06-04
  • 打赏
  • 举报
回复

void main()
{
HANDLE hThread1,hThread2,hThread3;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread3=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); //创建的三个线程利用的都是同一个线程函数,竟然不报错,为什么?

每个线程都会有自己的独立的运行空间,跟使用是不是同一个函数没关系,就像你在你的代码里面不同的地方调用同一个函数一样.

CloseHandle(hThread1);
CloseHandle(hThread2);
CloseHandle(hThread3);
while(1)
{

cout < <"main thread is running" < <endl;
}
}


DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
int i=0;
while(1)
{
i++; //每个线程利用的都是同一个i吗?如果不是,三个线程的代码区都是一样的,执行的都是同一段代码,那么这个i存放在什么地方??
不是同一个,除非你是 static int i;cout < <"i=" < <i < <endl; //这些i之间如何做到线程间的同步??
}
return 0;
}
  • 打赏
  • 举报
回复
这个这个文章贴出来方便看


一个函数被称作“线程安全”的,当且仅当它被多个线程反复调用时,它会一直产生令人期待的正确的结果。反之为“线程不安全”函数,它主要有两种类型:

(1)不保护共享变量的函数,包括全局变量和本地静态变量(static)。

我们可以使用POSIX信号量加以解决:

Sem_t mutex;

Sem_init(&mutex,0,1);

Sem_wait(&mutex);

……

……

Sem_post(&mutex);



优点:简单易行;

缺点:同步操作p、v将影响程序的执行时间。

(2)返回指向静态变量的指针的函数,如gethostbyname,gethostbyaddr,inet_ntoa等等。

我一般这样使用gethodtbyname:



Struct hostent *hostp;

Hostp=gethostbyname(scorpion.cublog.cn);

……

……


Gethostbyname将执行结果存放在自己的static struct hostent变量中,并返回一个指向这个结构的指针。如果我们从并发线程中调用这个函数,那么将发生不可预料的结果,正在被一个线程使用的结果,可能悄悄地被其它线程覆盖。

解决办法:(a)、改写库函数gethostbyname,增加一个参数,将本地结构变量传入gethostbyname,

如:

Struct hostent host;

Gethostbyname(&host,scorpion.cublog.cn);

再使用host方可!




(b)、改写库函数gethostbyname,不是返回指针,而是直接返回struct hostent.

缺点:struct hostent结构较大,影响函数的效率。



以上两种办法(a)、(b),要求修改库函数,基本上不可行!



(c)、使用lock –and-copy技术,即定义自己的封装函数,通过调用它来取代直接使用gethostbyname.



struct hostent *gethostbyname_my(char *hostname)

{

struct hostent *shar,*unshar;

unshar=malloc(sizeof(struct hostent))

sem_wait(&mutex);

shar=gethosybyname(hostname);

*unshar=*shar;

srm_post(&mutex);

return unshar;

}




现在大多数unix\linux操作系统,提供了线程不安全函数的可重入版本,如:gethostbyname_r。但是不同的系统可能接口不一样,所以建议不使用它们!还是使用我们自己的封装函数。



可重入函数,是线程安全函数的一种。特点:当它们被多个线程调用时,不会引用任何共享数据,也就是不引用静态或全局变量。如,gethostbyname_my是线程安全函数,而不是可重入函数。
  • 打赏
  • 举报
回复
http://topic.csdn.net/u/20070530/10/ec332c1b-fdf6-4f3b-b90d-2d79b2f04a80.html

你先搞明白什么叫线程安全函数,什么叫可重入函数吧。
  • 打赏
  • 举报
回复
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
int i=0;
while(1)
{
i++; //每个线程利用的都是同一个i吗?如果不是,三个线程的代码区都是一样的,执行的都是同一段代码,那么这个i存放在什么地方??
cout < <"i=" < <i < <endl; //这些i之间如何做到线程间的同步??
}
return 0;
}

楼主,你这里的线程函数里没有全局变量,都是局部变量,是可重入的,线程安全,当然可以。



[/code]
crst_zh 2009-06-04
  • 打赏
  • 举报
回复
每个线程都有自己的线程栈
zjw6861982 2009-06-04
  • 打赏
  • 举报
回复
3个线程独立执行,当然不会报错。
线程之间如果可能有冲突,那就是信号量互斥机制、内存机制的问题,没有执行函数是否同名的问题
BenjaminHuang 2009-06-04
  • 打赏
  • 举报
回复
线程入口函数是一段代码,执行特定的处理,所有线程都可以共享它。

这段代码所访问和操作的数据如果有全局可见的,那不同的线程并发执行时需要同步机制去保证处理的一致性。
jiahehao 2009-06-04
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 devilring 的回复:]
楼上的已经说得很清楚了,这里线程内部定义的i是局部变量,单独存放,每个线程函数启动后都会新开一段内存使用,所以3个线程中的i不会互相干扰
[/Quote]

nod
draculamx 2009-06-04
  • 打赏
  • 举报
回复
[Quote=引用楼主 tugouxp 的帖子:]

hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread3=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); //创建的三个线程利用的都是同一个线程函数,竟然不报错,为什么?
[/Quote]

不同的线程可以使用任何全局函数,不论是相同还是不同

[Quote=引用楼主 tugouxp 的帖子:]

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
int i=0;
while(1)
{
i++; //每个线程利用的都是同一个i吗?如果不是,三个线程的代码区都是一样的,执行的都是同一段代码,那么这个i存放在什么地方??
cout < <"i=" < <i < <endl; //这些i之间如何做到线程间的同步??
}
return 0;
}
[/Quote]

请注意你所说的 i 这个变量的作用域,i为 Fun1Proc 这个函数的局部变量,所以每一个使用 Fun1Proc 作为线程函数的线程,其中的 i 都是相互独立的,互不干扰。

如果是这样的话:


int i=0; //i为全局变量
//那么,所有使用 Fun1Proc 函数作为线程函数的线程,都将使用同一个i(即 i 在内存中只有一份)
//由于每个线程执行的先后顺序完全是不可知的,所以如果要让全局变量 i 得到正确的操作,就需要使用一些手段
//临界区,互斥体,信号量。。。。。这些东西楼主可以去 google 一下,也可以去找一些专门介绍多线程的书籍看一下

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{

while(1)
{
i++;
cout < <"i=" < <i < <endl;
}
return 0;
}

flora186 2009-06-04
  • 打赏
  • 举报
回复
lori227 2009-06-04
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 cftxlin 的回复:]
每个线程都有自己的堆栈空间,就是说每个线程在内存里头都有这些数据的一份。当然会不影响了!
[/Quote]

嗯!
bobby.x 2009-06-04
  • 打赏
  • 举报
回复
楼上的已经说得很清楚了,这里线程内部定义的i是局部变量,单独存放,每个线程函数启动后都会新开一段内存使用,所以3个线程中的i不会互相干扰
  • 打赏
  • 举报
回复
每个线程都有自己的堆栈空间,就是说每个线程在内存里头都有这些数据的一份。当然会不影响了!
wanggang_0717 2009-06-04
  • 打赏
  • 举报
回复
up
w29468 2009-06-04
  • 打赏
  • 举报
回复
函数就是代码,代码段是相同的,每个线程上下文信息中有自己的代码段指针,并不会冲突。每个线程的数据是自己的。对于局部数据不会冲突,对于全局数据有可能冲突,必要时需要加锁保护。
w0911h 2009-06-04
  • 打赏
  • 举报
回复
虽然用的同一个函数,但是三个线程是独立执行的,互不干扰,代码段相同,但是数据段不同,i只是函数内的一个局部变量,应该不涉及什么同步的东西,我也不是很懂,等待高手
加载更多回复(2)

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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