Linux系统编程-线程

全文内容来源于《UNIX环境高级编程-第三版》

文章目录

  • 线程创建
  • 线程终止
  • 取消线程
  • 线程清理处理程序
  • 进程线程原语对比
  • 线程分离
  • 线程同步
    • 互斥量-mutex
    • 读写锁
    • 条件变量
    • 自旋锁
    • 屏障

线程创建

#include 
int pthread_create(pthread_t *restrict tidp,
		const pthread_attr_t *restrict attr,
		void *(*start_rtn)(void *),void *restrict arg);
成功则返回0,否则返回错误编号

tidp指向新创建的线程的线程ID
新创建的线程从函数start_rtn处执行,参数为arg

如果新线程在主线程调用pthread_create返回之前就运行了,那么新线程看到的是未经初始化的ntid的内容,这个内容就不是正确的线程ID
Linux线程ID是用无符号长整形来表示的,但是它们看起来像指针。

线程终止

如果进程中的任意线程调用了exit,_Exit或者_exit,那么整个进程就会终止
单个线程可以通过3种方式退出,因此可以在不终止整个进程的情况下,停止它的控制流。、

  1. 线程可以简单的从启动例程中返回,返回值是线程的退出码
  2. 线程可以被同一进程中的其他线程取消
  3. 线程调用pthread_exit
#include 
void pthread_exit(void *rval_ptr);

rval_ptr参数是一个无类型参数,与传给启动例程的单个参数类似
进程中的其它线程可以通过调用pthread_join()函数访问到这个指针。

#include 
int pthread_join(pthread_t thread,void **rval_ptr); 
成功则返回0,否则返回错误编号

调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果线程简单的从它的启动例程返回,rval_ptr就包含返回码。如果线程被取消,由rval_ptr指向的内存单元就设置为PTHREAD_CANCELED。
如果对线程的返回值并不感兴趣,可以把rval_ptr设置为NULL,这种情况下,调用pthread)joing函数可以等待指定的线程终止,但并不获取线程的终止状态。

取消线程

#include 
int pthread_cancel(pthread_t tid);
成功返回0,否则返回错误编号

其他线程调用这个函数,但是并不等待线程终止,它仅仅提出请求

线程清理处理程序

#include 
void pthread_cleanup_push(void (*rtn)(void *),void *arg);
void pthread_cleanup_pop(int execute);

进程线程原语对比

进程原语 线程原语 描述
fork pthread_create 创建新的控制流
exit pthread_exit 从现有的控制流中退出
waitpid pthread_join 从控制流中得到退出状态
atexit pthread_cancel_push 注册到退出控制流中调用的函数
getpid pthread_self 获取控制流的ID
abort pthread_cancel 请求控制流的非正常退出

线程分离

#include 
int pthread_detach(pthread_t tid);

线程同步

互斥量-mutex

要点:
对共享资源访问时,加一把锁,当其他线程试图访问时会阻塞,知道锁被释放,这时所有等待这个锁的线程都会变成可运行状态,首先获得资源的再加锁,这样其他线程再阻塞等待

#include 
int phread_mutex_init(pthread_mutex_t *restrict mutex,
					const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
成功则返回0,否则返回错误编号

静态分配的互斥量可以用THREAD_MUTEX_INITIALIZER初始化

pthread_mutex_t  mutex = THREAD_MUTEX_INITIALIZER;

如果动态分配互斥量,在释放内存前需要调用上述destroy函数

使用下述函数加锁、解锁操作。
lock 加锁,如果已经上锁,阻塞。
unlock 解锁
trylock尝试加锁,不阻塞,如果之前已经加锁,返回EBUSY

#include 
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
成功则返回0,否则返回错误编号

死锁问题

pthread_mutex_timedlock与phread_mutex_lock基本上是等价的。但是在达到超时时间值时,pthread_mutex_timedlock不会对互斥量进行加锁,而是返回错误码ETIMEOUT。使用绝对时间,timespec结构

#include
#include 
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
					const struct timespec *restrict tsptr);
					

读写锁

#include 
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
			const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
成功则返回0,否则返回错误编号
#include 
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock);

成功则返回0,否则返回错误编号

条件变量

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

int pthread_cond_wait(pthread_cond_t *restrict cond,
				pthread_mutex_t *restrict mutex);
int pthread_cond_timtdwait(pthread_cond_t *restrict cond,
				pthread_mutex_t *restrict mutex
				const struct timespec *resitrct tsptr);

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

自旋锁

屏障

屏障是用户协调多个线程并行工作的同步机制,屏障允许每个线程等待,直到所有的合作线程都到达某一点,然后从该点继续执行。

#include 
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
				const pthread_barrierattr_t *restrict attr,
				unsigned int count );
int pthread_barrier_destroy(pthread_barrier_t *barrier);

你可能感兴趣的:(004-Linux)