线程create时参数的传递问题(转载)

1.奇怪的线程参数初始化

for( i=0; i

{

//会有什么问题?

pthread_create(&tid,NULL, &thread_client_function, (void*)&i );

}

上面代码应该很容易明白,创建多个线程,传入序列号作为线程id。基实这里存在一个大bug, 传递的参数会不成功!!

示例代码:

view plaincopy to clipboardprint?

#include   #include   #include   #include   #include   void* thread_client_function( void* param )  {  int client_id = *(int*)param;  printf("client id %d\n", client_id);  }  int main( int argc, char * argv[] )  {  int n = atol( argv[1] );  int i=0;  pthread_t tid;  for( i=0; i{  pthread_create(&tid,NULL, &thread_client_function, (void*)&i );  }  pthread_join( tid, NULL );  return 0;  }

输出:

gcc -o test_thread test_thread.c -lpthread

./test_thread 3

client id 3

client id 3

client id 3

为什么呢?注意其实传递时i是局部变量,而线程的创建是有延时的,所以当多次调用时,线程函数还没执行。但是这里i已经为3了。当线程函数开始执行,读入的参数自然都为3了,这个小细节真可谓令我大伤脑筋呀:)

稍作修改即可:

...

int * a = (int*)malloc( n* sizeof(int) );

for( i=0; i

{

a[i] = i;

pthread_create(&tid,NULL, &thread_client_function, (void*)&a[i] );

}

pthread_join( tid, NULL );

...

这样就可以保存参数不变了。

2. pthread_mutex_t / pthread_cond_t初始化/释放

作为一个全局变量时可以使用:

pthread_mutex_t g_mtx = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;

如果有多个可使用:

pthread_mutex_init( &g_mtx , NULL);

pthread_cond_init( &g_cond , NULL);

释放:

pthread_mutex_destroy( &g_mtx );

pthread_mutex_destroy( &g_mtx );

3. 同步条件pthread_cond_t使用

1)需要配合mutex使用

pthread_mutex_lock( &g_mtx );

pthread_cond_wait( &g_cond , &g_mtx );

pthread_mutex_unlock( &g_mtx );

使用pthread_cond_wait 需要在 lock/unlock 之间,以防止在进入wait状态前有signal。需要先lock, 一旦进行wait状态,会释放 mutex的lock。而一旦有收到signal信号就会自动重新获到mutex的lock。而且cond的lock是原子操作。

在需要的地方进行 pthread_cond_signal( g_cond ), 之前的wait 位置就可以执行,达到多个线程同步。

2)使用超时条件

struct timespec tv;

tv.tv_sec = time(0) + 1;

tv.tv_nsec = 0;

ret = pthread_cond_timedwait( &g_cond , &g_mtx ,&tv );

指定超时结构体timespec,注意超时时间是当前时间,所以要设定为time(0) + N秒。timespec 可精确到纳秒。

3)多个线程串行执行

只需要在全局设定一个处理序列号,这样每个线程在执行前判断是否为自己要处理的序号,否则继续wait, 处理框架如下:

void* thread_client_function( void* param )

{

int client_id = *(int*)param;

...

do

{

pthread_cond_wait( &g_conds[ i + 1 ] , &g_mtxs[i] );  //等待取得执行信号

}

while ( g_do[client_id][i] != g_idx ); //判断是否为当前处理序列,否则继续等待

...

}

void* thread_server_function( void* param )

{

...

for(i=0;i

{

printf("Server signal %d\n", i + 1 );

pthread_cond_signal( &g_conds[ i + 1 ] ); //唤醒多个处理线程

}

...

}

上面使用了多个cond的处理,也可以直接使用一个cond, 使用pthread_cond_broadcast响醒所有等待的线程。

时间: 2024-10-13 11:44:50

线程create时参数的传递问题(转载)的相关文章

verilog中defparam的用法 (verilog调用底层模块(只改变)参数的传递)

当一个模块引用另外一个模块时,高层模块可以改变低层模块用parameter定义的参数值,改变低层模块的参数值可采用以下两种方式: 1)defparam 重定义参数 语法:defparam path_name = value ; 低层模块的参数可以通过层次路径名重新定义,如下例: module top ( .....)input....;output....;defparam U1 . Para1 = 10 ;M1 U1 (..........);endmodulemodule M1(....);

[转载]DllMain中不当操作导致死锁问题的分析--线程退出时产生了死锁

(转载于breaksoftware的csdn博客) 我们回顾下之前举得例子 case DLL_PROCESS_ATTACH: { printf("DLL DllWithoutDisableThreadLibraryCalls_A:\tProcess attach (tid = %d)\n", tid); HANDLE hThread = CreateThread(NULL, 0, ThreadCreateInDllMain, NULL, 0, NULL); WaitForSingleO

(转载)你好,C++(26)如何与函数内部进行数据交换?5.1.3 函数参数的传递

你好,C++(26)如何与函数内部进行数据交换?5.1.3 函数参数的传递 5.1.3  函数参数的传递 我们知道,函数是用来完成某个功能的相对独立的一段代码.函数在完成这个功能的时候,往往需要外部数据的支持,这时就需要在调用这个函数时向它传递所需要的数据它才能完成这个功能获得结果.例如,当调用一个加法函数时,需要向它传递两个数作为加数和被加数,然后在它内部才能对这两个数进行计算获得加和结果.在定义一个函数的时候,如果这个函数需要跟外部进行数据交换,就需要在函数定义中加入形式参数表,以确定函数的

254 在js调用函数时,传递变量参数时, 是值传递还是引用传递

问题: 在js调用函数时,传递变量参数时, 是值传递还是引用传递 理解1: 都是值(基本/地址值)传递 理解2: 可能是值传递, 也可能是引用传递(地址值) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>02_关于数据传递问题</title> </head> <body> <

web页面中参数的传递方法

在web页面中参数的传递方法多样,主要有以下几种: Viewstate,Querystring,Session, Application,Cookie,Cache. Viewstate: 特点:服务启启动的各种控件的视图状态:包括控件的所有属性值:Enableviewstate可以启用和禁用视图状态:        优点:防止新产生一个页面实例后,丢失前一个页面的状态信息: 例如:在用户登录注册验证过程中,无须使用导致服务器往返行程的代码,我们只需要在客户端进行验证就可以了.另外有些控件的初始化

Mysql常用show命令,show variables like xxx 详解,mysql运行时参数

MySQL中有很多的基本命令,show命令也是其中之一,在很多使用者中对show命令的使用还容易产生混淆,本文汇集了show命令的众多用法. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 a. show tables或show tables from database_name; -- 显示当前数据库中所有表的名称. b. show databases; -- 显示mysql中所有数据库的名称. c. show columns from table_n

Swift 2.0学习笔记(Day 20)——函数中参数的传递引用

原创文章,欢迎转载.转载请注明:关东升的博客 参数的传递引用 类是引用类型,其他的数据类型如整型.浮点型.布尔型.字符.字符串.元组.集合.枚举和结构体全部是值类型. 有的时候就是要将一个值类型参数以引用方式传递,这也是可以实现的,Swift提供的inout关键字就可以实现.看下面的一个示例: func increment(inout value:Double, amount:Double = 1.0) { value += amount } var value : Double = 10.0

C#,往线程里传参数的方法总结

C#,往线程里传参数的方法总结 Thread (ParameterizedThreadStart) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托.   Thread (ThreadStart) 初始化 Thread 类的新实例.  由 .NET Compact Framework 支持.  Thread (ParameterizedThreadStart, Int32) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托,并指定线程的最大堆栈

线程退出时执行函数,处理资源

一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退出,这是可预见的退出方式: 非正常终止是线程在其他线程的干预下,或者由于自身运行出错(比如访问非法地址)而退出,这种退出方式是不可预见的. 不论是可预见的线程终止还是异常终止,都会存在资源释放的问题,在不考虑因运行出错而退出的前提下,如何保证线程终止时能顺利的释放掉自己所占用的资源, 特别是锁资源,就是一个必须考虑解决的问题. 最经常出现的情形是资源