天天看点

linux基础——线程

线程基础

线程的创建、退出、分离、汇合

创建线程使用pthread_create

代码示例

线程的退出

线程的汇合和分离

线程对共享资源(临界资源)的访问

线程同步

线程同步——mutex锁

线程同步——条件变量

线程同步——信号量

进程间通讯(IPC)信号量集

进程和程序

进程是资源分配的基本单位,而线程是执行的基本单位。

进程和线程的关系

一个进程中可以有多个线程,最少有一个线程(主线程)。线程共享进程的资源。每个线程有自己独有的属性,线程id(tid)、线程栈帧、线程自己的信号屏蔽字等。进程的切换和进程间的通讯,消耗资源非常大且效率低下。而线程共享进程的资源,线程的切换和线程间的通讯很灵活、消耗资源非常少、效率很高。

验证一个进程中有多个线程,需要获取到进程的pid和线程的tid,获取进程的pid使用getpid函数即可,而获取线程的tid则使用pthread_self函数

pthread_c.c

执行结果

linux基础——线程

return和exit的区别:

在线程函数中调用return只是线程执行函数的结束。代表了线程的结束。如果在线程函数中调用exit函数将会终止整个进程,那么进程中的所有线程都会终止。所以切记,一定不要在线程执行函数中调用exit等函数。

终止一个线程使用pthread_exit函数。

调用pthread_cancel函数将终止其它线程

线程创建后,线程退出的时候,线程的资源自动回收,不需要主线程等待,这样的线程称为分离线程。

线程的分离使用pthread_detach函数

线程创建以后,线程退出后需要其它线程来回收该线程的资源,这样的线程称为线程的汇合。

线程汇合使用pthread_join()函数。

pthread_e.c

linux基础——线程

线程创建完毕,进程中的所有线程都是异步的。

要保证线程函数的安全,那么线程函数必须是可重入的。如果线程函数是不可重入的,那么对临界资源的访问将造成程序的乱序。

pthread_t.c

linux基础——线程

多个线程对临界资源进行访问的时候,需要由异步变为同步。

POSIX线程中提供了三种方式来进行线程同步。

mutex锁

条件变量

信号量

pthread_mutex_init

pthread_mutex_lock

pthread_mutex_trylock

pthread_mutex_unlock

pthread_mutex_destroy

pthread_m.c

linux基础——线程

什么是条件变量?

线程间的同步有这样一种情况:线程A需要等待某个条件成立才会继续往下执行,如果条件不成立则阻塞等待,而线程B在执行过程中使得这个条件成立,然后唤醒线程A继续往下执行。那么这个条件就是条件变量。

pthread库中通过使用pthread_cond_t类型来表示条件变量类型。

对这种类型的操作包括以下:

pthread_cond_init(3)

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

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

int pthread_cond_destroy(pthread_cond_t *cond);

使用条件变量完成一个生产者和消费者的问题。

p_c.c

linux基础——线程

对于多个资源的共享使用信号量。

想使用其中的一个资源的时候,首先判断是否有可用资源。如果有,是资源的可用数量减1.如果没有可用资源,线程等待其他线程释放资源。当线程释放资源的时候,资源可用数量加1.

信号量是一个类型 sem_t

关于信号量的操作,系统提供了以下函数

sem_init(3)

sem_destroy(3)

sem_post(3)

sem_wait(3)

int sem_trywait(sem_t *sem);

使用信号量完成生产者和消费者模型,不再使用链表,使用循环队列完成。

p_cq.c

linux基础——线程

信号量集就是有一个或多个信号量组成的集合。

如何使用信号量集实现进程间的通讯?

获取一个键值。

通过键值获取信号量集semid。

semget(2)

对信号量集中的某一个信号量进行pv操作

使用函数semop(2)

为信号量集中的某一个信号量设置初值。或者获取信号量的值。

控制信号量集中某一个信号量,需要使用到semctl(2)

使用进程间通讯模仿TCP通讯结果。

server.c

client.c