Linux 下的多线程遵循POSIX标准,叫做pthread。编写Linux下的线程时,需要包含pthread.h头文件,在生成可执行文件时候需要链接libpthread.a或者libpthread.so
1.Linux下线程创建pthread_create()
#include
int pthread_create(
pthread_t *thread, //用于标识一个线程
pthread_attr_t *attr, // 用于设置线程的属性,如果为NULL ,则是默认属性
void *(*start_routine)(void *),// 当线程的资源分配成功后,线程中运行的单元。通常为一个函数
void *arg //线程函数运行时传入参数()
);
创建成功返回0;若不为零则线程创建失败
2.线程的结束函数pthread_join()和pthread_exit()
函数pthread_join()用来等待一个线程运行结束。这个函数是个阻塞函数,一直被等待的线程结束为止,函数才返回并且回收被等待线程的。
函数原型
extern int pthread_join __P((pthread_t __th,void **__thread_return));
//__th :线程标识符,就是pthread_create();//创建成功的值
//__thread_return ;:线程返回值,它是一个指针,用来存储被等待线程的值。
线程退出
extern void pthread_exit __p((void *__retval ))
3.线程其他API
设置线程为分离态:
int pthread_detach (pthread_t __th);
获取线程自己:
pthread_t pthread_self (void)
终止线程:
int pthread_cancel(pthread_t thread):
线程可以通过调用pthread_cancel函数来请求取消同一进程中的其线程。发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。注意pthread_cancel并不等待线程终止,它仅仅提出请求。
比较线程
int pthread_equal(pthread_t tid1, pthread_t tid2);
返回值: 相等返回非0, 不相等返回0.
说明: 比较两个线程ID是否相等.
4.线程的属性:pthread_attr_t
从上例中,用pthread_create() 函数创建线程时,使用了默认参数,将第二个参数设置为NULL,建立一个线程时候,使用默认属性就够了,但很多时候需要调整线程的属性,特别是线程的优先级;
typedef struct _pthread_attr_s{
int _detachstate; /*线程终止状态*/
int _schedpolicy; /*调度优先级*/
struct _sched_param _schedparam; /*参数*/
int _inheritsched; /*继承*/
int _scope; /*范围*/
size_t _guardsize; /*保证尺寸*/
int _stackaddr_set; /*运行栈*/
void *_stackaddr; /**线程运行栈的大小*/
size_t _stacksize; /**线程运行栈大小*/
}pthread_attr_t;
1) 线程的优先级
由两个优先级设置
函数:pthread_attr_getschedparam();获得线程的优先级
函数:pthread_attr_setschedparam();设置线程的优先级
//设置线程优先级
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
//获取线程优先级
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct schedparam *param);
线程的优先级存放在数据结构sched_param中(包含在sched.h中),操作方式是将优先级取出来,然后对需要设置的参数修改后再写回去。
例子如下:
#include
#include
#include
pthread_attr_t attr;
struct sched_param sch;
pthread_t pt;
pthread_attr_init(&attr);
/*获得当前线程属性**/
pthread_attr_getschedparam(&attr,&sch);
sch.sched_priority=256; /**设置优先级为256****/
pthread_attr_setschedparam(&attr,&sch); /**设置线程优先级**/
/**建立线程****/
pthread_create(&pt,&attr,(void *)start_rountin,&run);
/*****属性销毁***/
int pthread_attr_destroy(pthread_attr_t *attr);
5.线程互斥
互斥锁是用来保护一段临界区的,它可以保证某段时间内只有一个线程在执行一段代码或者访问 某个资源。
1.线程互斥的函数介绍:
#include
pthread_mutex_t mutex; /*互斥区**/
/*互斥锁初始化*/
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);
/****锁定互斥***/
int pthread_mutex_lock(pthread_mutex_t *mutex);
/*****互斥预锁定******/
int pthread_mutex_trylock(pthread_mutex_t mutex);
/***解锁互斥*******/
int pthread_mutex_unlock(pthread_mutex_t *mutex);
/****销毁互斥锁*******/
Int pthread_mutex_destroy(pthread_mutex_t *mutex);
6.条件变量
互斥锁和条件变量的属性
在前面的互斥锁和条件变量的讲解中,我们用两个常量PTHREAD_MUTEX_INITIALIZER和PTHREAD_COND_INITIALIZER来初始化它们。有这种方式初始化的互斥锁和条件变量具备默认属性,不过我们还能以非默认属性来初始化它们。
#include
//互斥锁代码初始化
int pthread_mutex_init(pthread_mutex_t *mptr,const pthread_mutex_mutexattr_t *attr);
int pthread_mutex_destory(pthread_mutex_t *mptr);
//条件变量代码初始化
int pthread_cond_init(pthread_cond_t *cptr,const pthread_cond_condattr_t *attr);
int pthread_cond_destory(pthread_cond_t *cptr);
条件变量(Condition):等待与信号发送
互斥锁用于上锁,条件变量用于等待。这两种不同类型的同步都是需要的。
条件变量是类型为pthread_cond_t的变量,以下两个函数使用了这些变量:
#include
int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);
int pthread_cond_signal(pthread_cond_t *cptr);
//均返回:若成功则为0,若出错则为正的Exxx值
条件变量:定时等待和广播
通常pthread_cond_signal只唤醒等待在相应条件变量上的一个线程。在某些情况下,一个线程认定有多个其他线程应被唤醒,这时它可以调用pthread_cond_broadcast唤醒阻塞在相应条件变量上的所有线程。
#include
int pthread_cond_broadcast(pthread_cond_t *cptr);
int pthread_cond_timewait(pthread_cond_t *cptr,pthread_mutex_t *mptr,const struct timespc *abstime);
对于pthread_cond_timewait(...),其允许线程就阻塞时间设置一个限制值。Abstime参数是一个timespec结构体,该结构体指定这个函数必须返回的时间,即便当时相应的条件变量还没收到信号,如果发生这种超时情况,该函数返回ETIMEDOUT错误。该时间值是绝对时间。而不是时间差。
7.Linux 的多线程编程案例
Linux 出租车案例代码实例
#include
// 提示出租车到达的条件变量
pthread_cond_t taxiCond;
// 同步锁
pthread_mutex_t taxiMutex;
// 旅客人数,初始为 0
int travelerCount=0;
// 旅客到达等待出租车
void * traveler_arrive(void * name) {
cout<< ” Traveler: ” <
pthread_mutex_lock(&taxiMutex);
// 提示旅客人数增加
travelerCount++;
pthread_cond_wait (&taxiCond, &taxiMutex);
pthread_mutex_unlock (&taxiMutex);
cout<< ” Traveler: ” << (char *)name << ” now got a taxi! ” <
pthread_exit( (void *)0 );
}
// 出租车到达
void * taxi_arrive(void *name)
{
cout<< ” Taxi ” <
{
pthread_mutex_lock(&taxiMutex);
// 当发现已经有旅客在等待时,才触发条件变量
if(travelerCount>0)
{
pthread_cond_signal(&taxtCond);
pthread_mutex_unlock (&taxiMutex);
break;
}
pthread_mutex_unlock (&taxiMutex);
}
pthread_exit( (void *)0 );
}
void main() {
// 初始化
taxtCond= PTHREAD_COND_INITIALIZER;
taxtMutex= PTHREAD_MUTEX_INITIALIZER;
pthread_t thread;
pthread_attr_t threadAttr;
pthread_attr_init(&threadAttr);
pthread_create(&thread, & threadAttr, taxt_arrive, (void *)( ” Jack ” ));
sleep(1);
pthread_create(&thread, &threadAttr, traveler_arrive, (void *)( ” Susan ” ));
sleep(1);
pthread_create(&thread, &threadAttr, taxi_arrive, (void *)( ” Mike ” ));
sleep(1);
return 0;
}
8.互斥锁封装
摘自libprocess源代码:
Synchronized.h
#include
class Synchronizable
{
public:
Synchronizable()
: initialized(false) {}
explicit Synchronizable(int _type)
: type(_type), initialized(false)
{
initialize();
}
Synchronizable(const Synchronizable &that)
{
type = that.type;
initialize();
}
Synchronizable & operator = (const Synchronizable &that)
{
type = that.type;
initialize();
return *this;
}
void acquire()
{
if (!initialized) {
}
pthread_mutex_lock(&mutex);
}
void release()
{
if (!initialized) {
}
pthread_mutex_unlock(&mutex);
}
private:
void initialize()
{
if (!initialized) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, type);
pthread_mutex_init(&mutex, &attr);
pthread_mutexattr_destroy(&attr);
initialized = true;
} else {
}
}
int type;
bool initialized;
pthread_mutex_t mutex;
};
class Synchronized
{
public:
explicit Synchronized(Synchronizable *_synchronizable)
: synchronizable(_synchronizable)
{
synchronizable->acquire();
}
~Synchronized()
{
synchronizable->release();
}
operator bool () { return true; }
private:
Synchronizable *synchronizable;
};
#define synchronized(s) \
if (Synchronized __synchronized ## s = Synchronized(&__synchronizable_ ## s))
#define synchronizable(s) \
Synchronizable __synchronizable_ ## s
#define synchronizer(s) \
(__synchronizable_ ## s)
#define SYNCHRONIZED_INITIALIZER Synchronizable(PTHREAD_MUTEX_NORMAL)
#define SYNCHRONIZED_INITIALIZER_DEBUG Synchronizable(PTHREAD_MUTEX_ERRORCHECK)
#define SYNCHRONIZED_INITIALIZER_RECURSIVE Synchronizable(PTHREAD_MUTEX_RECURSIVE)
使用方法:
#include
#include
#include
using namespace std;
#include
#include "Synchronized.h"
string generate(const string& prefix)
{
static map* prefixes = new map();
static synchronizable(prefixes) = SYNCHRONIZED_INITIALIZER;//初始化
int id;
synchronized (prefixes) {
int& _id = (*prefixes)[prefix];
_id += 1;
id = _id;
}
printf("%d\n", id);
return prefix + "(" + ")";
}
int main()
{
printf("%s\n", generate("heihei").c_str());
return 0;
}