您的位置:首页 > 运维架构 > Linux

Linux C++多线程编程

2014-12-12 11:27 344 查看
综合整理
http://blog.csdn.net/wpfyouran0012010/article/details/41842639?ref=myread http://www.cnblogs.com/BiffoLee/archive/2011/11/18/2254540.html http://www.cnblogs.com/feisky/archive/2009/11/12/1601824.html
Linux是一种多进程单线程的操作系统,本身只有进化的概念,所谓的“线程”本质上在内核里仍然是进程。Linux内核提供了轻进程的支持,来实现多线程。进程是资源分配的单位,同一个进程中的多个线程共享该进程的资源。

一、创建线程

进程创建是,系统会为其创建一个主线程,在进程中创建新的线程使用 pthread_create函数:

#include <pthread.h>
int pthread_create(pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void *),void *arg);
pthread_t pthread_self(void);
int pthread_equal(pthread_t thread1,pthread_t thread2);
int pthread_once(pthread_once_t *once_control,void(*init_routine)(void));</span>


      第一个参数为线程标示符,第二个参数用来设置线程属性,第三个参数是线程运行的函数的起始地址,第四个参数是线程运行函数的参数。

 

     线程ID 在创建的时候返回到 thread_id 

二、线程退出

1)执行完成后隐式退出;

2)由线程本身显式调用pthread_exit(void* retval)函数退出

3)被其他线程用pthread_cance函数终止

         pthread_cance(pthread_t thread_id)

如果一个线程要等待另一个线程的终止,可以使用pthread_ioin函数,调用其函数的线程将被进程挂起直到线程ID为参thread_id的线程终止。

         extern int pthread_join __P ((pthread_t __th, void **__thread_return));

三、线程属性设置

初始化的函数为pthread_attr_init 这个函数必须在pthread_create函数之前调用

/* man pthread_attr_init */
typedef struct
{
int                    detachstate;    //是否与其他线程脱离同步
int                    schedpolicy;    //新线程的调度策略
struct sched_param    schedparam;        //运行优先级等
int                    inheritsched;    //是否继承调用者线程的值
int                    scope;            //线程竞争CPU的范围(优先级的范围)
size_t                guardsize;        //警戒堆栈的大小
int                    stackaddr_set;    //堆栈地址集
void *                stackaddr;        //堆栈地址
size_t                stacksize;        //堆栈大小
} pthread_attr_t;


属性对象主要包括:1、是否绑定  2、是否分离 3、堆栈地址、堆栈大小  4、 优先级  

默认的属性为非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级

1、是否绑定    轻进程可以控制一个或多个线程,默认情况下,启动多少轻进程、哪些轻进程控制哪些线程是由系统来控制,此即非绑定的。绑定状况下,某个线程固定绑在一个轻进程上。  被绑定的线程具有较高的响应速度。通过设置被绑定的轻进程的优先级和调度级,可以使绑定的线程满足诸如实时反应之类的要求。

  

<span style="font-size:12px;">#include <pthread.h>
pthread_attr_t attr;
pthread_t tid;
/*初始化属性值,均设为默认值*/
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_create(&tid, &attr, (void *) my_function, NULL);</span>


2、是否分离

非分离状态,原有线程等待创建的线程结束,只有当 pthread_join()函数返回时,创建的线程才算终止,释放自己占用的资源内存。

分离线程自己运行结束线程自动终止,马上释放系统资源。  注意此时如果程序运行的很快,可能在pthread_create函数返回之前就终止了,此时会发生混乱,可以在被创建的线程里调用pthread_cond_timwait函数,让线程等待一会儿。

pthread_attr_setdetachstate(pthread_attr_t
*attr, int detachstate)第二个参数可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD _CREATE_JOINABLE(非分离线程)

在对待线程结束时,要确保该线程处于 detached 状态,否着就需要调用 pthread_join() 函数来对其进行资源回收

3、线程优先级

它存放在结构sched_param中。用函数pthread_attr_getschedparam和函数pthread_attr_setschedparam进行存放,一般说来,我们总是先取优先级,对取得的值修改后再存放回去。

<span style="font-size:12px;"><pre name="code" class="cpp">#include <pthread.h>
#include <sched.h>
pthread_attr_t attr;
pthread_t tid;
sched_param param;
int newprio=20;
pthread_at
4000
tr_init(&attr);
pthread_attr_getschedparam(&attr, ¶m);
param.sched_priority=newprio;
pthread_attr_setschedparam(&attr, ¶m);
pthread_create(&tid, &attr, (void *)myfunction, myarg);</span>


四、线程数据

单线程程序内有全局变量和局部变量,在多线程程序里,还有第三种数据类型:线程数据。  和全局变量很想,但是在线程内部各个函数可以像使用全局变量一样调用,对线程外部其他线程是不可见的。我们为每个线程数据创建一个键,它和这个键相关联,在各个线程里,都使用这个键来指代线程数据,但在不同的线程里,这个键代表的数据是不同的,在同一个线程里,它代表同样的数据内容。线程私有数据采用了一键多值的技术,即一个键对应多个数值,访问数据时好像是对同一个变量进行访问,但其实是在访问不同的数据。

创建私有数据的函数有4个:pthread_key_create(创建),
pthread_setspecific(设置), pthread_getspecific(获取), pthread_key_delete(删除)。

#include <pthread.h>
int pthread_key_creadte(pthread_key_t *key,void (*destr_fuction) (void *));
int pthread_setspecific(pthread_key_t key,const void * pointer));
void * pthread_getspecific(pthread_key_t key);
int pthread_key_delete(ptherad_key_t key);


五、线程通信
线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点。linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和异步信号。

1、线程互斥

互斥意味着“排它”,即两个线程不能同时进入被互斥保护的代码。Linux下可以通过pthread_mutex_t
定义互斥体机制完成多线程的互斥操作,该机制的作用是对某个需要互斥的部分,在进入时先得到互斥体,如果没有得到互斥体,表明互斥部分被其它线程拥有,此时欲获取互斥体的线程阻塞,直到拥有该互斥体的线程完成互斥部分的操作为止。 

通过锁机制实现线程间的同步。同一时刻只允许一个线程执行一个关键部分的代码。

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex *mutex);
int pthread_mutex_destroy(pthread_mutex *mutex);
int pthread_mutex_unlock(pthread_mutex *

void reader_function ( void );
void writer_function ( void );
char buffer;
int buffer_has_item=0;
pthread_mutex_t mutex;
struct timespec delay;
void main ( void ){
pthread_t reader;
/* 定义延迟时间*/
delay.tv_sec = 2;
delay.tv_nec = 0;
/* 用默认属性初始化一个互斥锁对象*/
pthread_mutex_init (&mutex,NULL);
pthread_create(&reader, pthread_attr_default, (void *)&reader_function), NULL);
writer_function( );
}
void writer_function (void){
while(1){
/* 锁定互斥锁*/
pthread_mutex_lock (&mutex);
if (buffer_has_item==0){
buffer=make_new_item( );
buffer_has_item=1;
}
/* 打开互斥锁*/
pthread_mutex_unlock(&mutex);
pthread_delay_np(&delay);
}
}
void reader_function(void){
while(1){
pthread_mutex_lock(&mutex);
if(buffer_has_item==1){
consume_item(buffer);
buffer_has_item=0;
}
pthread_mutex_unlock(&mutex);
pthread_delay_np(&delay);
}
}


2、线程同步

同步就是线程等待某个事件的发生。只有当等待的事件发生线程才继续执行,否则线程挂起并放弃处理器。当多个线程协作时,相互作用的任务必须在一定的条件下同步。 

Linux下的C语言编程有多种线程同步机制,最典型的是条件变量(condition variable)。pthread_cond_init用来创建一个条件变量,其函数原型为:

int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);//pthread_cond_wait和pthread_cond_timedwait用来等待条件变量被设置,值得注意的是这两个等待调用需要一个已经上锁的互斥体mutex,这是为了防止在真正进入等待状态之前别的线程有可能设置该条件变量而产生竞争。
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);  //解除所有线程的阻塞


#include<stdio.h>
#include<pthread.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
void *thread1(void *arg)
{
pthread_cleanup_push(pthread_mutex_unlock,&mutex);
printf("thread1 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf("thread1 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(1);
pthread_cleanup_pop(0);
}
void *thread2(void *arg)
{
pthread_cleanup_push(pthread_mutex_unlock,&mutex);
printf("thread2 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf("thread2 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(1);
pthread_cleanup_pop(0);
}
int main()
{
pthread_t thid1,thid2;
printf("condition variable study!\n");
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&thid1,NULL,(void*)thread1,NULL);
pthread_create(&thid2,NULL,(void*)thread2,NULL);
int i;
sleep(2);
pthread_cond_signal(&cond);
sleep(1);
pthread_cond_signal(&cond);
sleep(1);
pthread_join(thid1,NULL);
pthread_join(thid2,NULL);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 多线程 c++