# 创建线程

/* 查看当前线程ID */
typedef unsigned long int pthread_t;
pthread_t pthread_self(void);
/* 创建进程 */
union pthread_attr_t
{
  char __size[__SIZEOF_PTHREAD_ATTR_T];
  long int __align;
};
typedef union pthread_attr_t pthread_attr_t;
int pthread_create(pthread_t *newthread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
/*
Description:
	newthread:传出参数,创建的新线程ID
	addr:线程的属性,一般情况使用默认值即可,NULL
	start_routine:函数指针,创建出的子进程的处理函数,也就是在子线程中需要执行的函数
	arg:作为实参传递到start_routine指针指向的函数内部
Return Value:
	线程创建成功返回0,否则返回对于的错误码
*/

# 线程退出

void pthread_exit(void *retval);
/*
Description:
	只要调用该函数,当前线程立马退出,并且不影响其他线程的运行,不管是在子进程还是主进程中都可以使用
	retval:线程退出时携带的数据,当前子线程的主进程会得到该数据。如果不需要,指定为NULL。
*/

# 线程回收

int pthread_join(pthread_t thread, void **retval);
/*
Description:
	用于在子进程退出后,主进程回收子进程的内核资源。该函数为一个堵塞函数,如果子进程还在运行,调用该函数就会堵塞,子线程退出函数解除堵塞,并将线程占用的内核资源回收。
	thread:子进程的进程ID
	retval:二级指针,指向一级指针的地址,是一个传出参数,这个地址中存储了pthread_exit()传递出的数据,如果不需要这个参数,可以指定为NULL。
Return Value:
	线程回收成功返回0,回收失败返回错误码。
*/

# 线程分离

在某些情况下,程序中的主线程有属于自己的业务处理流程,如果让主线程负责子线程的资源回收,调用 pthread_join() ,只要子线程不退出,主线程就会被一直堵塞,主线程的任务也就不能被执行。

int pthread_detach(pthread_t thread);
/*
Description:
	调用线程分离函数之后,指定的子线程就可以和主线程分离,当子进程退出的时候,其占用的内核资源就会被系统的其他线程接管并回收。线程分离之后,主线程中使用的pthread_join()就回收不到子线程的资源了。
	thread:子线程ID
*/

# 线程取消

int pthread_cancel(pthread_t thread);
/*
Description:
	在一个线程中杀死另外一个线程。使用这个函数杀死一个线程需要分两步:
	1. 在线程A中调用线程取消函数pthread_cancel(),指定杀死线程B。
	2. 线程B中执行一次系统调用时才会被杀死,否则仍然存活。
*/

# 线程 ID 比较

int pthread_equal(pthread_t t1, pthread_t t2);
/*
Description:
	t1,t2为需要比较的两个线程ID。
Return Value:
	如果两个线程ID相等返回一个非0值,如果不等则返回0
*/

# 线程同步

# 互斥锁

互斥锁是线程同步最常用的一种方式,通过互斥锁可以锁定一个代码块。被锁定的代码块,所以线程只能顺序执行。

pthread_mutex_t mutex;
/* 初始化互斥锁 */
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *attr);
/*
	mutex: 互斥锁变量地址
	attr: 互斥锁的属性,一般使用默认属性即可,这个参数指定为NULL
	返回0,则初始化成功,否则返回错误码
*/
/* 释放互斥锁 */
int pthread_mutex_destroy(pthread_mutex_t *mutex);
/* 上锁 */
int pthread_mutex_lock(pthread_mutex_t *mutex);
/*
Description:
	这个函数被调用,实现会判断参数mutex互斥锁中的状态是不是锁定状态:
		- 没有锁定,则这个线程可以加锁成功,这个锁会记录是哪一个线程加锁成功了
		- 如果被锁定,其他线程加锁就失败了,这些线程都会被堵塞在这把锁上
		- 当这把锁被解开之后,这些堵塞在锁上的线程就会解除堵塞,并且这些线程通过竞争的方式对这把锁加锁,没抢到锁的进程继续堵塞
*/
/* 尝试加锁 */
int pthread_mutex_trylock(pthread_mutex_t *mutex);
/*
Description:
	尝试对mutex互斥锁进行加锁:
		- 若互斥锁没有被锁定,线程加锁成功
		- 若互斥锁被锁定,调用这个函数加锁的线程,不会被堵塞,加锁失败直接返回错误码
*/

/* 解锁 */
int pthread_mutex_unlock(pthread_mutex_t *mutex);
/*
Description:
	并不是所以的线程都可以对互斥锁解锁,那个线程加的锁,那个线程才可以解锁。
*/

# 死锁

当多个线程访问共享资源,需要加锁,如果锁使用不当,就会造成死锁这种现象。

# 读写锁

读锁是共享的,写锁是独占的;写锁比读锁优先级高;如果临界区涉及大量的读操作,使用读写锁比使用互斥锁效率高,而只有少量的读操作,则互斥锁和读写锁效率差异不大

pthread_rwlock_t rwlock;
/* 初始化读写锁 */
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
/* 销毁读写锁 */
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
/* 加读锁 */
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
/* 尝试加读锁,加锁失败不堵塞 */
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
/* 加写锁 */
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
/* 尝试加写锁,加锁失败不堵塞 */
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
/* 解锁(读锁 / 写锁) */
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

# 条件变量

一般情况下条件变量用于处理生产者和消费者模型,并且和互斥锁配合使用。条件变量类型为 pthread_cond_t ,被条件变量堵塞的线程以及线程信息会被记录到这个变量中,以便在解除堵塞时使用。

pthread_cond_t cond;
/* 初始化 */
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condaddr_t *restrict attr);
/* 销毁释放资源 */
int pthread_cond_destroy(pthread_cond_t *cond);
/* 堵塞当前线程 / 进程 */
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *mutex);
struct timespec{
    time_t tv_sec;
    long tv_nsec;
};
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *mutex, const struct timespec *restrict abstime);
/* 唤醒堵塞在条件变量上的一个线程 */
int pthread_cond_signal(pthread_cond_t *cond);
/* 唤醒所以堵塞在条件变量上的线程 */
int pthread_cond_broadcast(pthread_cond_t *cond);

# 信号量

#include <semaphore.h>
sem_t sem;
int sem_init(sem_t *sem, int pshared, unsigned int value);
/*
	sem: 信号量变量地址
	pshared: 0 表示线程同步;非 0 表示进程同步
	value: 初始化当前信号量拥有的资源数
*/
int sem_destroy(sem_t &sem);
int sem_wait(sem_t *sem);
int sem_try_wait(sem_t *sem);
/* 产看信号量 sem 当前拥有的资源个数,通过第二个参数传出(返回值也可以) */
int sem_getvalue(sem_t *sem, int *sval);
int sem_post(sem_t *sem);
Edited on Views times

Give me a cup of [coffee]~( ̄▽ ̄)~*

Value WeChat Pay

WeChat Pay