Linux系统编程--线程控制(二)

一、私有数据

1.特殊的变量

多线程环境下,进程内的所有线程共享进程的数据空间,因此全局变量为所有线程共有。在程序设计中有时需要保存线程自己的全局变量,这种特殊的变量仅在某个线程内部有效。举例来说,errno它返回标准的出错代码,errno不应该为局部变量,几乎每个函数都应该可以访问它,但它又不能为全局变量,否则在一个线程里输出的很可能是另一个线程的出错信息。这个问题可以通过创建线程的私有数据(Thread-specific Data ,或TSD)来解决。

2.TSD池(关键数据结构数组)

创建一个TSD就相当于将结构体数组中的某一项设置为”in_use”,并将其索引返回给*key,然后设置destructor函数为destr_function。

3.一键多值

线程私有数据采用了一键多值的技术,。访问数据时都是通过键值来访问。操作线程私有函数的主要函数有4个

#include <pthread.h>
int pthread_key_creat(pthread_key_t *key, void (*destr function) (void*));
int pthread_setspecific(pthread_key_t key, const void * pointer);
void *pthread_getspecific(pthread_key_t key);
int pthread_key_delete (pthread_key_t key);

pthread_key_creat:从YSD池中分配一项,将其值赋给key供以后访问使用。
pthread_setspecific:将pointer的值(不是内容)与key相关联。
pthread_getspecific:得到与key相关联的数据。
pthread_key_delete:删除一个键。

实现创建和使用线程的私有数据
这里写图片描述
运行结果
这里写图片描述

注:两个线程分别将tsd作为线程私有数据,从结果可以看出,两个线程tsd的修改互不干扰。线程终止时使用了pthread_exit(),即使主线程退出了,其他线程也会继续运行。

二、线程同步

1.互斥锁

互斥锁通过锁机制来实现线程间的同步问题。在同一时刻它通常只允许一个线程执行一个关键部分的代码

#include <pthread.h>
pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
//初始化一个互斥锁
pthread_mutex_destroy(pthread_mutex_t *mutex);
//注销一个互斥锁
pthread_mutex_lock(pthread_mutex_t *mutex);
//加锁,如果不成功,阻塞等待
pthread_mutex_unlock(pthread_mutex_t *mutex);
//解锁
pthread_mutex_trylock(pthread_mutex_t *mutex);
//测试加锁,如果不成功则立即返回,错误码为EBUSY
[1].初始化互斥锁

除了使用pthread_mutex_init()函数初始化,还可用静态赋值法

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
[2].加锁

用pthread_mutex_lock()加锁时,如果mutex已经被锁住,当前尝试加锁的线程就会阻塞,直到互斥锁被其他线程释放。

[3].解锁

pthread_mutex_unlock()解锁时,要满足两个条件:a.互斥锁必须处于加锁状态,b.调用本函数的线程必须是给互斥锁加锁的线程。
当一个互斥锁用完后,必须进行清除。

[4]. 注销

清除一个互斥锁意味着释放它所占用的资源。清除锁时要求当前处于开放状态,若锁处于锁定状态,函数返回EBUSY,该函数执行成功时返回0。

2.条件变量

条件变量是利用线程间共享的全局变量进行同步的一种机制。使用条件变量主要包括两个动作:一个等待使用资源的线程等待“条件变量被设置为真”;另一个线程在使用完资源后“设置条件为真”,这样就可以保证线程间的同步。

pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
//初始化条件变量
pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
//基于条件变量阻塞,无条件等待
pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespc *abstime);
//阻塞直到指定事件发生,计时等待
pthread_cond_signal(pthread_cond_t *cond);
//解除特定线程的阻塞,存在多个等待线程时,按入队顺序激活其中一个
pthread_cond_broadcast(pthread_cond_t *cond);
//解除所有线程的阻塞
pthread_cond_destroy(pthread_cond_t *cond);
//清除条件变量
[1].初始化

除了使用函数pthread_cond_init()之外,还可以用静态赋值法
pthread_cond_t cond = PTHREAD_COND_INITLALIZER;

[2].等待条件成立

pthread_cond_wait函数释放由mutex指向的互斥锁,同时使当前线程关于cond指向的条件变量变阻塞,直到条件被信号唤醒。pthread_cond_timedwait用法类似,差别在于 pthread_cond_timedwait函数将阻塞直到条件变量获得信号或者经过由abstime指定的时间,也就是说,如果他在指定时间前条件没有满足,则返回ETLMEOUT,结束等待。

[3].激活

线程被条件变量阻塞后,可被激活。

[4].清除

只有在没有线程等待该条件变量的时候才能清除这个条件变量,否则返回EBUSY。

演示条件变量的使用方法
这里写图片描述
这里写图片描述
运行结果
这里写图片描述

3.异步信号

线程可以接收和处理信号,信号也是一种线程间同步的手段

int pthread_kill(pthread_t threadid, int signo);
int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask);
int sigwait(const sigset_t *set, int *sig);

三、出错处理

1.错误码

错误码是一些定义在errno.h中的宏,通常以字母E开头。

2.错误检查

头文件errno.h定义了变量errno,它存储了错误发生时的错误码,通过错误码可以得到错的描述信息。

3.错误的提示信息

1.strerror
#include<string.h>
char *strerror(int errnum);

streeror函数根据参数errnum提供的错误码获取一个描述错误信息的字符串,函数的返回值为指向该字符串的指针,errnum的值通常就是errno。

2.perror
#include<stdio.h>
void perror(const char *message);

perror打印错误信息到stderr。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值