pthread_cond_t, pthread_cond_broadcast()与 pthread_mutex_t
2016-01-12 18:07
381 查看
pthread线程使用小结
1.奇怪的线程参数初始化
for( i=0; i<n; 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<n; 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<n; i++ )
{
printf("Server signal %d\n", i + 1 );
pthread_cond_signal( &g_conds[ i + 1 ] ); //唤醒多个处理线程
}
...
}
上面使用了多个cond的处理,也可以直接使用一个cond, 使用pthread_cond_broadcast响醒所有等待的线程。
1.奇怪的线程参数初始化
for( i=0; i<n; i++)
{
//会有什么问题?
pthread_create(&tid,NULL, &thread_client_function, (void*)&i );
}
上面代码应该很容易明白,创建多个线程,传入序列号作为线程id。基实这里存在一个大bug, 传递的参数会不成功!!
示例代码:
01.#include <stdio.h> 02.#include <stdlib.h> 03.#include <unistd.h> 04.#include <pthread.h> 05.#include <memory.h> 06.void* thread_client_function( void* param ) 07.{ 08.int client_id = *(int*)param; 09.printf("client id %d/n", client_id); 10.} 11.int main( int argc, char * argv[] ) 12.{ 13.int n = atol( argv[1] ); 14.int i=0; 15.pthread_t tid; 16.for( i=0; i<n; i++) 17.{ 18.pthread_create(&tid,NULL, &thread_client_function, (void*)&i ); 19.} 20.pthread_join( tid, NULL ); 21.return 0; 22.}
输出:
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<n; 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<n; i++ )
{
printf("Server signal %d\n", i + 1 );
pthread_cond_signal( &g_conds[ i + 1 ] ); //唤醒多个处理线程
}
...
}
上面使用了多个cond的处理,也可以直接使用一个cond, 使用pthread_cond_broadcast响醒所有等待的线程。
相关文章推荐
- Java设计模式 建造模式(Builder)
- 关于ImportError: xxxx.so: undefined symbol: PyFPE_jbuf的解决方案
- 低功耗蓝牙4.0BLE编程-nrf51822开发(5)-链路层
- android5.1 MT6735 编译过程
- MySQL手册 DATE_ADD() 函数向日期添加指定的时间间隔。
- 低功耗蓝牙4.0BLE编程-nrf51822开发(4)
- 关于html5里object、embed、video、audio的小总结
- iOS:如何通过UIEdgeInsetsMake来制作可伸缩的Button
- C# Emit动态代理生成一个实体对象
- WEBADI权限设置
- vxbox共享文件夹设置后ubuntu自动加载mount
- 低功耗蓝牙4.0BLE编程-nrf51822开发(3)
- 嵌入式系统的BootLoader技术浅析_启动过程
- 三步教会你装系统
- linux的文件类型和权限
- 在virtualbox里把Ubuntu下安装的中文输入法切换出来
- Windows7 下编译 OSGEarth
- git rebase vs git merge
- JS中的toFixed()四舍五入方法
- tomcat 内存调整