linux应用基础知识点17-线程和线程同步

linux应用基础知识点17-线程和线程同步

线程

一个进程可以有多个线程,一个线程必属于一个进程。
进程实现多任务的缺点:
1.进程间切换的成本大
2.进程间通信麻烦且效率低
线程的引入:
1.保留了进程多任务的特性
2.线程间切换和通信效率更高
3.多线程在多核心cpu上可实现真正并发运行。

pthread_create函数

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

该函数用来创建一个线程。
thread用来接收子线程的id;
attr为线程的属性,默认可设为NULL;
start_routine为子线程程序;
arg为线程的参数,无参数可设为NULL。

pthread_self函数

pthread_t pthread_self(void);

该函数用来获取线程的id。

pthread_join函数

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

主线程阻塞等待回收线程。

pthread_detach函数

int pthread_detach(pthread_t thread);

主线程分离子线程,分离后不必去回收子线程。

pthread_cancel函数

int pthread_cancel(pthread_t thread);

一个线程可以向另一个线程发出取消命令,让其立即结束。线程取消的配合函数:

  1. pthread_setcancelstate (子线程设置自己是否允许被取消[被结束]):
    PTHREAD_CANCEL_ENABLE//允许被取消 PTHREAD_CANCEL_DISABLE //不许被取消
  2. pthread_setcanceltype (子线程设置自己被取消采取的方式,其前提是允许被取消):
    PTHREAD_CANCEL_DEFERRED//等待到可以结束时才结束(如握有资源未释放时。。。)
    PTHREAD_CANCEL_ASYNCHRONOUS//立即结束

pthread_exit函数

void pthread_exit(void *retval);

retval用来接收线程结束的返回值,该返回值会最终传给pthread_join函数的参数中。
注意:线程结束可以使用pthread_exit或return结束该进程;使用exit会让整个进程结束。

pthread_cleanup_push函数

void pthread_cleanup_push(void (*routine)(void *),void *arg);

该函数的作用是,当线程非正常结束(被pthread_cancel结束)时,可能握有一些资源未释放(如互斥锁),此时清理压入函数中注册的功能函数routine会被调用,该功能函数可以帮助清理释放。

pthread_cleanup_pop函数

void pthread_cleanup_pop(int execute);

如果线程正常结束了,可以使用该函数取出压入的函数。参数为0时,取出丢弃该注册的函数;参数为1时,取出并且调用该注册的函数。

两函数的使用类似于压栈/出栈操作,先注册的函数后调用。如:

//。。。子线程程序。。。
void thread(void *arg) 
{                         
	pthread_cleanup_push(func1, arg);
	pthread_cleanup_push(func1, arg);
	//.....子线程主体程序
	pthread_cleanup_pop(0);
	pthread_cleanup_pop(0);
	pthread_exit();
}                   

线程同步

应用场景:
子线程阻塞等待被激活,当主线程有工作需要子线程处理时,让其从阻塞状态激活并工作。

线程同步的方法:
信号量、互斥锁、条件变量

信号量

(参见文章《linux应用基础知识点12-IPC之信号量》)

互斥锁

互斥锁(即互斥量)是一种特殊的信号量,其值非0即1,0代表锁定,1代表解锁。互斥锁主要用来实现资源上锁保护。比如有一段代码需要严格保护操作(不能中途被占用甚至修改某资源),则在该段代码前上锁,在该段代码后解锁。

互斥锁初始化:

int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              			const pthread_mutexattr_t *restrict attr);

mutex为被初始化的互斥锁对象;
attr为锁的属性,默认属性可设为NULL。

锁定互斥锁:

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);

补充:man 该函数时可能找不到,是因为没有按照线程相关的man手册。解决办法是: sudo apt-get install
manpages-posix-dev.

条件变量

条件变量用来自动阻塞一个线程,直到某条件发生为止。

条件变量初始化:

int pthread_cond_init(pthread_cond_t *restrict cond,
              const pthread_condattr_t *restrict attr);

cond为要初始化的条件变量;
attr为属性,如果使用默认属性可设为NULL;
成功返回值为0,错误返回错误编号。

等待条件变量:

int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex,
              const struct timespec *restrict abstime);

pthread_cond_wait为阻塞等待,pthread_cond_timedwait为超时等待。

通知条件变量:

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

pthread_cond_signal一次只能激活一个阻塞的线程,pthread_cond_broadcast一次则可以激活所有阻塞中的线程。

条件变量销毁:

int pthread_cond_destroy(pthread_cond_t *cond);

应用例程.
条件变量一般会配合互斥锁进行使用。下面是线程2通知线程1条件变量的程序框架:

线程1.

pthread_mutex_lock(&mutex);//互斥锁锁定
while(xxx)	//条件如果不成立
	pthread_cond_wait(&cond, &mutex);	//阻塞等待条件成立
//注意这里用的互斥锁和上面的锁是一个锁
。。。//线程执行
pthread_mutex_unlock(&mutex);//互斥锁解锁

线程2.

pthread_mutex_lock(&mutex);//互斥锁锁定
。。。//修改条件,使线程1的条件满足
pthread_cond_boadcast(&cond);	//激活等待的进程,通知条件已经满足
pthread_mutex_unlock(&mutex);//互斥锁解锁

解读:这里有人会疑惑,既然线程1将互斥锁锁上了,线程2怎么还能获得互斥锁呢。这是因为pthread_cond_wait的内部实现机制:

1.当pthread_cond_wait阻塞时,操作系统将该线程放在线程等待队列中,然后解锁互斥锁。
2.等到有pthread_cond_signal或pthread_cond_broadcast通知信号后,线程去竞争锁。
3.竞争到互斥锁则加锁,然后进行之后的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值