细谈linux下的posix多线程编程

POSIX线程概述

定义:一个程序中的多个执行路线叫做线程,线程是一个进程内部的控制序列。所有的进程都至少有一个执行线程(初始线程)。初始线程随进程的创建而创建,其他线程则需要通过显式的函数调用来创建。

实现posix线程的主要函数。

①创建新线程

#include <pthread.h>

int pthread_create(
         pthread_t * thread,                 //返回指向线程标识符的指针
         pthread_attr * attr,                 //设置线程属性
         void *(*func)(void*),               //新线程将启动的函数的地址
         void * arg );                            //传递给新线程启动函数的参数(注意类型的强制转换)

说明:函数执行成功返回0,失败返回错误码。执行成功后,新线程将从设定的函数处开始执行,原线程则继续执行。

 

②退出线程

#include <pthread.h>

void pthread_exit(void * ret);

说明:终止调用此函数的线程,并返回一个指向某对象的指针(ret)。注意,不能返回指向局部变量的指针。注意:在主线程中调用pthread_exit,进程将等待所有线程结束后才终止。


③合并线程

#include <pthread.h>

int pthread_join(pthread_t  thread, void **ret);

说明:等价于进程中用于收集子进程的wait()函数,thread 是要等待的线程(即通过pthread_creat函数返回的线程标识符),ret是一个二级指针,它指向一个指针,后者指向线程的返回值。函数执行成功时返回0,失败时返回错误码。pthread_join的功能是等待某线程结束,并收集其返回值。初始线程结束后(从main函数返回),整个进程即结束,导致进程内所有线程全部终止。在主线程中调用pthread_exit,进程将等待所有线程结束后才终止。

下面实现一个简单的多线程编程的例子。

 

线程同步:

       线程体现了程序执行的并发性(并行:并发、同时),多个线程并发执行,且同一进程内部的多个线程可以共享除局部变量之外的所有变量。用信号量同步线程用于线程同步,有四个处理函数:

#include <semaphore.h>

sem_t是用于同步的信号量
//初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int val); 

pshared:信号量类型,如为0,则为当前进程独享的信号量。
val:信号量的初始值。
//信号量减1
int sem_wait(sem_t *sem);
//信号量加1
int sem_post(sem_t *sem);
//销毁信号量
int sem_destory(sem_t *sem)

 

下面的例子验证了两个线程是并发执行的,其中一个线程用于读入用户输入的字符串,另一个线程用于统计字符串的长度。

 

线程互斥:

用互斥量同步线程互斥量允许程序员原子性的锁住某对象,使得每次只有一个线程可以访问它。

互斥量基本函数

#include <pthread.h>
//初始化互斥量
int pthread_mutex_init(pthread_mutex * mutex,const pthread_mutexattr_t * mutexattr);
//互斥量加锁
int pthread_mutex_lock(pthread_mutex * mutex);
//互斥量解锁
int pthread_mutex_unlock(pthread_mutex * mutex);
//销毁互斥量
int pthread_mutex_destroy(pthread_mutex * mutex);

 

      程序需要仔细设计,避免死锁。下面的例子验证了两个线程是并发执行的,其中一个线程用于读入用户输入的字符串,另一个线程用于统计字符串的长度,线程在对共享区域(char str_buf[BUFFER_SIZE])操作时先对其加锁,操作完毕后解锁。

 

线程属性:

创建线程时可以指定线程的属性,需要首先创建一个属性对象,然后用这个属性对象作为参数去创建线程。

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);

属性举例

如果不需要新创建的线程向主函数返回参数,也不需要初始线程等待新创建的线程执行结束,此时可以指定新线程的属性为分离属性。

#include <pthread.h>

int pthread_attr_setdetachstate(
              pthread_attr_t* attr                 //属性对象
              int detachstate  );                     //属性值
PTHREAD_CREATE_DETACHED:分离线程,无需(严格来说是不可以)使用pthread_join()函数合并。 
PTHREAD_CREATE_JOINABLE:允许其他线程合并此线程。

 

 

线程取消:

线程可以终止另一个线程

#include <pthread.h>

int pthread_cancel(pthread_t  thread);

thread:需要取消的线程标识符,由pthread_creat()返回。

 

线程需要设置是否允许被其他线程终止,即设置自己的取消状态

#include <pthread.h>

int pthread_setcancelstate(int state, int *oldstate);

state: PTHREAD_CANCEL_ENABLE:允许自身被其他线程取消。  PTHREAD_CANCEL_DISABLE:不允许被取消。

oldstate:返回先前的取消状态。

 

线程还需要设置自己的取消类型

#include <pthread.h>

int pthread_setcanceltype(int type, int *oldtype);

type:

PTHREAD_CANCEL_ASYNCHRONOUS:接收到取消请求后立即取消。

PTHREAD_CANCEL_DEFERRED:接到取消请求后,一直等待到线程执行了下述函数才取消——pthread_join,pthread_cond_wait,pthread_cond_timedwait,pthread_testcancel,sem_wait,sigwait。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章