linux线程学习

一、线程的创建和退出

1.函数原型

#include <pthread.h>
int pthread_create(pthread_t* thread,pthread_attr_t* attr,void *(*start_routine)(void*),void *arg);
void pthread_exit(void *retval);
pthread_t pthread_self(void);
				通用形式
pthread_t pthid;
int pthread_create(&pthid,NULL,pthFunc,NULL)或pthread_create(&pthid,NULL,pthFunc,(void*)3);
pthread_exit(NULL)或pthread_exit((void*)3);//3作为返回值被pthread_join函数扑获

2.各参数描述

	参数thread是传出参数,保存新进程的标识
	参数attr是一个结构体指针,结构体中的元素分别指定新线程的运行属性
	参数start_routine是一个函数指针,指向新线程的入口点函数,线程入口函数带有一个void*的参数,由pthread_create的第四个参数传入
	参数arg用于传递给第三个参数指向的入口点函数的参数

函数pthread_exit表示线程的退出,其参数可以被其他线程用pthread_join函数捕获

二、线程的等待退出

1.等待线程退出

	int pthread_join(pthread_t th,void **thread_return);

(1)该函数是一个阻塞函数,一直等到参数th指定的线程返回。thread_return是一个传出参数,接收线程函数的返回值。如果线程通过调用pthread exit()终止,则该函数内的参数相当于自然返回值,照样可以被其他线程用pthread_join获得。
(2)th传递0值时,join返回ESRCH错误
(3)易错点 pthread_join(pthid,(void**)&iRet);
(4)该函数还有一个非常重要的作用,由于一个进程的多个线程共享数据段,因此通常在一个线程退出后,退出线程所占的资源并不会随线程的结束而释放。如果线程类型不是自动清理资源类型的,则线程退出后,线程本身的资源必须通过其他线程调用pthread_join来清除。
(5)该函数不回收堆内存的,只回收线程的栈内存和内核中的struct task_struct结构占用的

2.线程的取消

int pthread_cancel(pthread_t thread);

(1)线程取消的方法是一个线程向目标线程发cancel信号,但是如何处理cancel信号则由目标线程来决定,目标线程或者忽略,或者立即终止,或者继续运行到取消点后终止
(2)取消点(camcelation-point)

pthread_join()
pthread_cond_wait();
sem_wait();
sigwait();
read();
write();
printf();
getchar();
sleep();
......

3.线程终止清理函数

void pthread_cleanup_push(void (*routine)(void*),void *arg)
void pthread_cleanup_pop(int execute);

(1)清理函数采用先入后出的栈结构管理
(2)void routine(void *arg)函数在调用pthread_cleanup_push()时压入清理函数栈。必须成对出现
(3)pthread_cleanup_pop的参数如果为非0值时,则按照栈的顺序注销掉一个原来注册的清理函数,并执行该函数;如果参数为0时,仅仅在pthread_exit函数或者其他线程对本线程调用pthread_cancel函数时,才弹出“清理函数”的同时执行“清理函数”。

三、线程的同步和互斥

1.线程的互斥

(1)创建与销毁锁
以静态方式:定义宏来静态初始化互斥锁

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

以动态方式:采用pthread_nutex_init()函数来初始化互斥锁

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr)

其中mutexattr是指互斥锁属性,通常为NULL;
注销一个互斥锁

int pthread_mutex_destroy(pthread_mutex_t *mutex);

销毁一个互斥锁即意味着释放它所占的资源,且要求锁处于开放状态 。检查锁的状态,如果是锁定状态则返回EBUSY

初始化一个快速锁:

pthread_mutex_t lock;
pthread_mutex_init(&lock,NULL);

(2)互斥锁的属性设置

PTHREAD_MUTEX_TIMED_NP  (NULL)
PTHREAD_MUTEX_RECURSIVE (允许一个线程对同一个锁成功获得多次,并通过多次unlock解锁)(递归锁)
pthread_mutex_errorcheck (检错锁)
示例:
pthread_mutex_t lock;
pthread_mutexattr_t mutexattr;
pthread_mutexattr_settype(&mutexattr,PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&lock,&mutexattr);

(3)锁操作

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);

加锁操作时,不论是哪种类型的锁,都不能被两个不同的线程同时得到,而必须等待解锁。对于普通锁,解锁者可以是同进程的任何线程;而检错锁则必须由加锁者解锁才有效,否则返回EPERM;对于嵌套锁,文档和实现要求必须由加锁者解锁。在同一进程中的线程,如果加锁后没有解锁,则任何其他线程都无法获得锁

解锁操作时,对于快速锁,该函数解除锁定;对于递归锁,该函数使锁上的引用计数减一;对于检错锁,如果锁是当前线程锁定时,则解除锁定,否则什么也不做

测试加锁,与加锁操作不同的是在锁已经占据时返回EBUSY而不是挂起等待

(4)注意
如果线程在加锁后解锁前被取消,锁将永远保持锁的状态,因此如果在关键区内有取消点在,则必须在退出回调函数pthread_cleanup_push/pthread_cleanup_pop中解锁,同时不应该在信号处理函数中使用互斥锁

2.线程的同步

(1)条件变量:利用线程间共享的全局变量进行同步的一种机制,主要有两个动作,一是线程等待条件变量的条件成立而挂起 ,二是线程使条件成立。条件变量的使用总是和一个互斥锁在一起
(2)创建 条件变量 动态

int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *condattr);
int pthread_cond_destroy(pthread_cond_t *cond);

注销一个条件变量时,只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY
(3)等待和激发
等待条件有两种方式:无条件等待和计时等待

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

线程解开mutex指向的锁并被条件变量cond阻塞。
激发条件有两种形式:

pthread_cond_signal();
pthread_cond_broadcast();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值