分类: LINUX
2013-08-29 16:17:56
pthread线程使用小结
1.奇怪的线程参数初始化
for( i=0; i { //会有什么问题? pthread_create(&tid,NULL, &thread_client_function, (void*)&i ); } 上面代码应该很容易明白,创建多个线程,传入序列号作为线程id。基实这里存在一个大bug, 传递的参数会不成功!! 示例代码: 输出: 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响醒所有等待的线程。