线程执行函数linux,Linux多线程编程——线程调用函数时传入参数

当调用pthread_create  第三个和第四个参数不为空时,要注意第四个参数的传递方法。

一段流行的代码:

#include

#include

using namespace std;

#define NUM_THREADS 10

void* say_hello(void* args)

{

int i = *((int*)args);//对传入的参数进行强制类型转换,由无类型指针变为整形数指针,然后再读取;

cout << "hello in " << i << endl;

}

int main()

{

pthread_t tids[NUM_THREADS];

cout << "hello in main..." << endl;

for(int i = 0; i < NUM_THREADS; ++i)

{

int ret = pthread_create(&tids[i], NULL, say_hello, (void *)&i);//传入的时候必须强制转换为void* 类型,即无类型指针

cout << "Current pthread id =" << tids[i] << endl;//这里学会使用tids数组打印创建的进程id信息;

if (ret != 0)

{

cout << "pthread_create error: error_code=" << ret << endl;

}

}

pthread_exit(NULL);

}

程序运行结果:

hello in main...

Current pthread id =140210171029248

Current pthread id =140210162636544

Current pthread id =140210154243840

Current pthread id =140210145851136

Current pthread id =140210137458432

Current pthread id =140210129065728

Current pthread id =140210120673024

Current pthread id =140210112280320

hello in 6

hello in 6

hello in 6

hello in 6

hello in hello in 6

hello in 6

7

Current pthread id =140210103887616

Current pthread id =140210095494912

hello in 10

hello in 10

hello in 10

显然与预期不一致,我猜想原因:我们 pthread_create的时候,传入i的方式是 取i的地址指针 再强制转换为 无类型指针,然后在sayhello函数里,再把无类型指针转换为int类型指针(这样做是为了满足phtread_create的参数设定),再通过 * 号取值。这意味着,我们是通过指向 i 的指针来获取i的值的,但是在多个线程切换间,i 的值已经改变了,但是指向 i 的地址并没有改变,多个线程随机竞争执行,所以通过 i 的地址 取值,显然取到的结果和预期的很难一致。

流行的一种做法:把 i 赋值给一个数组保存,这样就避免了在同一地址取值。

#include

#include

using namespace std;

#define NUM_THREADS 10

void* say_hello(void* args)

{

cout << "hello in thread " << *((int *)args) << endl;

}

int main()

{

pthread_t tids[NUM_THREADS];

int indexes[NUM_THREADS];//用个数组来保存i的值,就不会变了

for(int i = 0; i < NUM_THREADS; ++i)

{

indexes[i] = i;//先保存i的值,在调用线程就不会出现问题了

int ret = pthread_create( &tids[i], NULL, say_hello, (void *)&(indexes[i]) );

if (ret != 0)

{

cout << "pthread_create error: error_code=" << ret << endl;

}

}

for (int i = 0; i < NUM_THREADS; ++i)

pthread_join(tids[i], NULL);

}

运行结果:

hello in main..

Current pthread id = 140457201362688

Current pthread id = 140457192969984

Current pthread id = 140457184577280

Current pthread id = 140457176184576

Current pthread id = 140457167791872

Current pthread id = 140457159399168

Current pthread id = 140457151006464

Current pthread id = 140457142613760

Current pthread id = 140457134221056

Current pthread id = 140457125828352

hello in 3

hello in 4

hello in 5

hello in 6

hello in 7

hello in 8

hello in 9

hello in 2

hello in 1

hello in 0

还有一种写法也可以: 直接把 i 的值 强制转换成 无类型指针 传过去,然后再 在 被调函数里 把无类型指针参数 强制转换回来,注意,在64 位Linux机里,指针是8个字节,int是4个字节,long也是8个字节,所以必须转换成long型,否则会因丢失精度而报错。从这里也可以看出来,第一个程序结果和预期不一致 不是因为 i 的值和预期不一致,而是 i 的地址出问题了。

#include

#include

using namespace std;

#define NUM_THREADS 10 //线程数

void* say_hello( void* args )

{

cout << "hello in " << long(args) <<  endl;

}

int main()

{

pthread_t tids[NUM_THREADS]; //线程id

cout << "hello in main.." << endl;

for( int i = 0; i < NUM_THREADS; ++i )

{

int ret = pthread_create( &tids[i], NULL, say_hello, (void*)i );

//直接把i的值传过去

cout << "Current pthread id = " << tids[i] << endl;

//用tids数组打印创建的进程id信息

if( ret != 0 ) //创建线程成功返回0

{

cout << "pthread_create error:error_code=" << ret << endl;

}

}

for( int i = 0; i < NUM_THREADS; ++i )

{

pthread_join(tids[i],NULL);

}

}

运行结果:

hello in main..

Current pthread id = 140406320125696

Current pthread id = 140406311732992

Current pthread id = 140406303340288

Current pthread id = 140406294947584

Current pthread id = 140406286554880

Current pthread id = 140406278162176

Current pthread id = 140406269769472

Current pthread id = 140406261376768

Current pthread id = 140406252984064

Current pthread id = 140406244591360

hello in 6

hello in 7

hello in 8

hello in 9

hello in 5

hello in 4

hello in 3

hello in 2

hello in 1

hello in 0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值