多线程编程

本文深入探讨了Linux环境下多线程编程,包括线程创建、同步机制如互斥锁、信号量和条件变量的使用。通过实例代码详细解释了如何实现线程的同步与通信,强调了线程同步在避免数据竞争和资源管理中的重要性。同时,介绍了线程的退出方式、状态管理以及线程的分离与结合状态,为多线程编程提供了实用的知识和技巧。
摘要由CSDN通过智能技术生成

学习目标:

一、与多进程关系
二、线程相关操作
三、线程同步

学习内容:

一、
1、解决进程的缺点
2、小于进程的基本单位
3、共享进程地址空间
4、多进程更健壮
二、
1、由线程库提供#include <pthread.h>

2、原型:
int pthread_create((pthread_t *thread, pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)

3、头文件
#include"stdio.h"
#include"pthread.h"
#include"stdlib.h"

4、

void *test1(void *arg)
{
   while (1)
    {
        printf("Testing\n");
        sleep(1);
    }
}

int main()
{
	pthread_t id;
	int ret = pthread_create(&id,NULL,test1,NULL);
	if(ret != 0)
	{
	perror("pthread creadte error!\n");
	exit(1);
	}
	
	pause();// 作用:使调用进程(线程)进入休眠状态(挂起);直到接收到信号且信号函数成功返回 pause函数才会返回
  //返回值:始终返回-1
    return 0;

}

5、编译
gcc xc.c -o xc -lpthread
6、退出
主动退出:pthread_exit
返回值:成功返回0,失败返回非零值

被动退出:pthread_cancel(id)
当次线程是死循环时,调动该函数主动取消该线程。
返回值:成功返回0,失败返回非零错误号。
只有发生系统调用的时线程才结束

注册退出:
pthread_cleanup_push
pthread_cleanup_p
7、等待(线程连接):pthread_join
等待子线程结束,并回收子线程资源。
pthread_join(id, NULL);

8、线程分离:pthread_detach

9、清理函数(push和pop必须成对出现)
void pthread_cleanup_push(void (* routine)(void *), void *arg);
void pthread_cleanup_pop(int execute)
说明:
pthread_cleanup_push(!0):主动弹栈
pthread_cleanup_push(0): 就是不弹栈
pthread——cleanup——pop(!0):自动弹栈

10、线程状态
可结合态:
这种状态下的线程是能被其他进程回收资源或被杀死的
如果一个可结合态线程不用pthread_join回收,则会变成类似僵尸进程
可分离态:
不能被其他进程回收资源或被杀死的,它存储的资源在它终止时由系统自动回收
为了避免存储器泄漏,每个可结合线程需要显示的调用pthread_join回收;
要么就将其变成分离态的线程
默认情况下,线程是可结合态。

三、
互斥锁,线程信号量,条件变量
1、互斥锁(进程退出时销毁互斥锁)
pthread_mutex_t mutex;

pthread_mutex_lock(&mutex);(阻塞加锁)访问临界区加锁操作
pthread_mutex_trylock()(非阻塞加锁)当锁被占用时返回EBUSY而不是挂起等待
pthread_mutex_unlock(&mutex)(解锁)
2、信号量
使用步骤:
(1)定义信号量集合
sem t sem【3】
线程信号量集合其实就是一个数组,数组每个元素就是一个信号量

sem 【0】:第一个信号量
sem【1】:第二个信号量
sem【2】:第三个信号量
)
(2)初始化集合中的每个信号量
#include "semaphore.h”
int sem_init(sem_t *sem,int pthread, unsigned int value)
功能:
初始化线程信号量集合中的某个信号量,给它设置一个初值
返回值:成功返回0,失败返回-1,erroo被设置
信号量的错误号不是返回的,而是直接设置到errno
value:初始化值(对于二进制信号量来说,要么是1,要么是0)
pshared:0:给线程使用,!0可以给进程使用

(3)p,v操作
p操作:
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

v操作:
int sem post(sem t *sem);
sem_wait value
假如你获得的时候别人已经获得了这个信号量(value值减1),你阻塞

P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.

(4)进程结束时,删除线程信号量集合
3、条件变量(和互斥锁配合使用)
一条线程做自加,一条线程输出,当自家变量到5输出之后自加变量清零
条件变量的主要作用(线程访问):主线程对count+1,次线程发现当count==5时输出count的值并将count清零。

多线程配合工作时,当线程检测到某条件不满足时就休眠,直到别的线程将条件准备好,然后通过条件变量将其叫醒。
使用步骤
(1)定义一个变量
pthread_coud_t
(2)初始化
pthread coud_init(pthread coud_t *restrict cond,const pthread_condattr_t *restrit attr);
功能:初始化条件变量,与互斥锁化类似
pthread——cond_t_cond = PTHREAD COND_INITIALIZER;
返回值:
成功返回0,不成功返回非零错误号
参数:
cond:条件变量

(3)使用条件变量
(4)删除条件变量,也需要把互斥锁删除

学习时间:

学习产出:

在这里插入图片描述

本文线程同步借鉴@浮生随意 写的不错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值