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。