线程同步学习

news2024/11/15 4:37:07

1、线程同步的定义

线程同步不是一起、相同,而是协调、协同的意思。
1)按预定的先后次序进行运行,如:您说完,我再说;线程A生成数据后交给线程B处理;
2)公共资源同一时刻只能被一个线程使用;共享数据在同一时刻只能被一个线程修改,以保证数据的完整性。

线程安全的3大特性
1、原子性
原子性是指操作是不可分的。其表现在于对于共享变量的某些操作,应该是不可分的,必须连续完成。
2、可见性
可见性是指一个线程对共享变量的修改,另外一个线程能够立刻看到;
基于互斥锁、条件变量、信号量、自旋锁、读写锁。

2、互斥锁

互斥锁是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。在任一时刻,互斥锁的状态只有两种:开锁或闭锁。当有任务(或线程)持有时,互斥锁处于闭锁状态,该任务获得互斥锁的所有权;当任务释放互斥锁时,它变为开锁状态,任务失去所有权。
作用:通过互斥锁,可以确保在任何给定的时间点,只有一个线程能够获得对临界区(即被互斥锁保护的资源区域)资源的访问权,从而避免多个线程同时访问和修改共享资源导致的数据竞争和不一致问题

临界资源:多线程中都能访问到的资源
临界区:每个线程内部,访问临界资源的代码,就叫临界区
1)初始化锁。
iht pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);

2)阻塞加锁,若互斥锁已经被其它线程上锁,则调用者一直阻塞等待,直到被解锁后才上锁。
int pthread_mutex_lock(pthread_mutex_t *mutex);

3)非阻塞加锁/若互斥锁未加锁,则上锁,若互斥锁已加锁,则函数立即返回失败。
int pthread_mutex_trylock(pthread_mutex_t*mutex);

4)解锁。
int pthread_mutex_unlock(pthread_mutex_t*mutex);

5)销毁锁, 释放资源(锁也是资源)。
int pthread_mutex_destroy(pthread_mutex_t *mutex);
#include<stdio.h>
#include<pthread.h>
#include<string.h>

char buffer[101];
pthread_mutex_t mutex;//声明互斥锁

void*pthfun(void*arg)
{
	for(int i=0;i<3;i++){
		printf("%ld:lock....\n",(long)arg);
		pthread_mutex_lock(&mutex);//加锁
		printf("%ld:lock is ok\n",(long)arg);
		sprintf(buffer,"%ld %d",pthread_self(),i);
		sleep(5);
		pthread_mutex_unlock(&mutex);//解锁
		printf("%ld:unlock....\n",(long)arg);
		usleep(100);
	}
}
int main()
{
	pthread_mutex_init(&mutex,NULL);//初始化锁

	pthread_t pthid1,pthid2;
	pthread_create(&pthid1,NULL,pthfun,(void*)1);
	pthread_create(&pthid1,NULL,pthfun,(void*)2);
	
	pthread_join(pthid1,NULL);
	pthread_join(pthid2,NULL);
	
	pthread_mutex_destroy(&mutex); //销毁锁
	
	return 0;
}

io复用使用多线程服务器

互斥锁实现数据库连接池(或者线程池)

先初始化数据库连接池,每个连接服务器的客户端需要使用数据库,就从连接池里拿一个数据库连接(也拿了锁),每次释放连接时也释放锁。
除此之外,还可以利用事务的特性保证线程安全。

  1. 原子性(Atomic)
    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 一个事务包含多个操作,这些操作要么全部执行,要么全都不执行
  2. 隔离性(Isolation)
    并发事务之间互相影响的程度,比如一个事务会不会读取到另一个未提交的事务修改的数据。事务的隔离性

3、条件变量

条件变量用来阻塞一个线程,直到其它的线程通知它条件已满足为止。
条件变量看似简单,与互斥锁同时使用时非常巧妙。生产消费者模型(高速缓存队列)。

1)初始化条件变量
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

2)阻塞等待
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

3)超时等待
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex*mutex, const timespecabstime);

4)唤醒一个等待该条件的线程
int pthread_cond_signal(pthread_cond_t *cond);

5)唤醒全部等待该条件的所有线程
int pthread_cond_broadcast(pthread_cond_t *cond);

6)销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>

char buffer[101];
pthread_mutex_t mutex;//声明互斥锁
pthread_cond_t cond; //声明条件变量

void*pthfun1(void*arg)
{
	while(1){
		pthread_cond_wait(&cond,&mutex);
		printf("线程1唤醒\n");
	}
}
void*pthfun2(void*arg)
{
	while(1){
		pthread_cond_wait(&cond,&mutex);
		printf("线程2唤醒\n");
	}
}
void func(int sig)
{
	pthread_cond_signal(&cond);
	
	//pthread_cond_broadcast(&cond);
}
int main()
{
	signal(15,func);
	pthread_mutex_init(&mutex,NULL);
	pthread_cond_init(&cond,NULL);
	
	pthread_t pthid1,pthid2;
	pthread_create(&pthid1,NULL,pthfun1,NULL);
	pthread_create(&pthid1,NULL,pthfun2,NULL);
	
	pthread_join(pthid1,NULL);
	pthread_join(pthid2,NULL);
	
	pthread_mutex_destroy(&mutex); //销毁锁
	
	return 0;
}

在这里插入图片描述

条件变量和互斥锁

pthread_cond_wait(&cond,&mutex);发生了这些步骤(释放锁,等条件变量,加锁)

  1. 释放了互斥锁
  2. 等待条件
  3. 条件被触发、 互斥锁加锁 第3步是原子操作
#include<stdio.h>
#include<pthread.h>
#include<string.h>

#include<unistd.h>
#include<signal.h>

char buffer[101];
pthread_mutex_t mutex;//声明互斥锁
pthread_cond_t cond; //声明条件变量

void*pthfun1(void*arg)
{
	while(1){
		pthread_mutex_lock(&mutex);  //加锁
		printf("线程1开始等待条件\n");
		pthread_cond_wait(&cond,&mutex);
		printf("线程1唤醒\n");
		pthread_mutex_unlock(&mutex);
	}
}
void*pthfun2(void*arg)
{
	while(1){
		pthread_mutex_lock(&mutex);
		printf("线程2开始等待条件\n");
		pthread_cond_wait(&cond,&mutex);
		printf("线程2唤醒\n");
		pthread_mutex_unlock(&mutex);
	}
}
void func(int sig)
{
	pthread_cond_signal(&cond);
	
	//pthread_cond_broadcast(&cond);
}
int main()
{
	signal(15,func);
	pthread_mutex_init(&mutex,NULL);
	pthread_cond_init(&cond,NULL);
	
	pthread_t pthid1,pthid2;
	pthread_create(&pthid1,NULL,pthfun1,NULL);
	pthread_create(&pthid1,NULL,pthfun2,NULL);
	
	pthread_join(pthid1,NULL);
	pthread_join(pthid2,NULL);
	
	pthread_mutex_destroy(&mutex); //销毁锁
	
	return 0;
}

在这里插入图片描述

实现高速缓存

4、信号量

信号量是一个整数计数器,其数值可以用于表示空闲临界资源的数量。
当有进程释放资源时,信号量增加,表示可用资源数增加;当有进程申请到资源时,信号量减少,表示可用资源数减少。

1)初始化信号量。   
int sem_init(sem_t*sem, int pshared,unsigned int value);
pshared :指定信号量的作用域。其值可以是 0 或非 0(通常是 1)。如果 pshared 的值为 0,则表示信号量仅在同一进程的线程之间共享。即,它用于
线程间的同步。如果 pshared 的值为非 0(通常是 1),则表示信号量可以在多个进程之间共享。但是,需要注意的是,要使得信号量在多个进程间共
享,可能需要将其放置在一个由这些进程共享的内存区域中(如通过 mmap 创建的映射区域或使用 shmget 创建的共享内存段)
value:指定了信号量的初始值。信号量的值表示可用资源的数量

2)等待信号量,如果信号量的值为0则等待,如果信号量大于0则返回,同时对值做减1操作。
int sem_wait(sem_t*sem);
int sem_trywait(sem_t*sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

3)释放信号量,信号量加1操作。
int sem post(sem_t *sem);

4)获取信号量的值。
int sem_getvalue(sem_t *sem, int *sval);

5)销毁信号量,释放资源。
int sem_destroy(sem_t *sem);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2078337.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp 小程序支持打开手机相册和摄像头

开发uniapp 时&#xff0c;有时需要让用户上传手机相册或者拍摄图片&#xff0c;对图片进行处理&#xff0c;下面提供了一个method&#xff0c;支持打开摄像头拍照和相册功能&#xff0c;完成后&#xff0c;对图片做base64处理。 // 打开相册的方法openCamera() {let _thisthi…

给自己复盘的tjxt笔记day9

优惠券管理 开发流程 需求分析&#xff0c;接口统计&#xff0c;数据库设计&#xff0c;创建分支&#xff0c;创建新模块&#xff08;依赖&#xff0c;配置&#xff0c;启动类&#xff09;&#xff0c;生成代码&#xff0c;引入枚举状态 优惠券管理 增删改查的业务代码&#…

vagrant 创建虚拟机

创建一个名为 “Vagrantfile” 的文件&#xff0c;修改如下内容&#xff1a; Vagrant.configure("2") do |config|(1..3).each do |i|config.vm.define "k8s-node#{i}" do |node|# 设置虚拟机的Boxnode.vm.box "centos/7"# 设置虚拟机的主机名…

Behave使用体验

behaveuiautomator2jenkins 同理&#xff0c;Behave也可以和Appium/AirTest框架结合 运行环境 pip install uiautomator2 behave behave2cucumber 意事项&#xff1a;behave版本号建议1.2.5&#xff0c;因为1.2.6和Jenkins Cucumber Report插件不兼容 生成报告 html报告 …

各位,请入局AI大模型,现在!立刻!马上!!

AI 大模型人才供不应求 2024年&#xff0c;AI 在国内市场全面大爆发&#xff0c;不断涌现出新的算法、模型和应用场景&#xff0c;各行各业的垂类大模型应用也迎来井喷期。 无论是华为、 百度、阿里、字节等互联网巨头&#xff0c; 还是中小型的科技公司都在高薪挖 AI 大模型人…

易盾空间推理 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我…

Codeforces Round 968 (Div. 2) ABC题详细题解(C++,Python)

前言&#xff1a; 本文为Codeforces Round 968 (Div. 2)的ABC详细题解&#xff0c;包含C,Python语言描述&#xff0c;觉得有帮助或者写的不错可以点个赞 感觉D题说的好抽象&#xff0c;看不懂&#xff0c;之后实力够了更新 目录 题A: 题目大意和解题思路: 代码实现(C): 代…

全国大学生数学建模大赛——黄花鱼的最优捕捞策略

渔业管理部门规定&#xff0c;每年只允许在产卵孵化期前的8个 月进行捕捞作业。如果每年投入的捕捞能力(如渔船数、下网 次数等)固定不变&#xff0c;这时单位时间捕捞量将与各年龄组鱼群条 数成正比&#xff0c;比例系数不妨设为捕捞强度系数。通常使用 13mm 网眼的拉网&…

中国高校发表科技论文及著作数量数据集(2009-2022年)

中国各地区的高校科技产出数据&#xff0c;包括27个指标&#xff0c;科技论文发表、著作出版、专利申请、专利转让、国家标准项等。这些指标综合反映了各地区高校在科学研究和技术开发方面的活跃程度及创新能力 一、数据介绍 数据名称&#xff1a;中国地区高校发表科技论文、…

Android App启动流程

1.通过 Launcher 启动应用时&#xff0c;点击应用图标后&#xff0c;Launcher 调用 startActivity 启动应用。 2.Launcher Activity 最终调用 Instrumentation 的 execStartActivity 来启动应用。 3.Instrumentation 调用 ActivityManagerProxy (ActivityManagerService 在应…

计算机类-本科毕业设计快速通关攻略-(选题-创新点-论文框架-论文绘图)

一、推荐选题 大多数人都没有什么基础&#xff0c;不推荐做系统类的&#xff0c;建议走深度学习方向&#xff0c;简单易上手&#xff0c;下面将给出几个我认为不错的方向。 1、目标检测类 目标检测是每年深度学习毕业设计的主流&#xff0c;如Faster R-CNN、YOLO、SSD等算法…

程序员心理健康测试问卷

当然&#xff0c;以下是一份针对程序员设计的心理健康测试问卷。这份问卷旨在帮助程序员评估自己的心理健康状态&#xff0c;并识别可能存在的心理问题。请注意&#xff0c;此问卷仅供参考&#xff0c;不能替代专业心理咨询或诊断。 程序员心理健康测试问卷 基本信息 姓名&am…

为什么不让程序员直接对接客户,而是通过产品经理?

从客户的角度来说&#xff0c;客户需要的是对自身业务的解决方案以及实现&#xff0c;即能够实现解决方案的软件或系统。从程序员的角度来讲&#xff0c;甲方说啥&#xff0c;我按着做就行了&#xff0c;即实现甲方说的软件或系统。但是甲方不懂技术&#xff0c;程序员不懂业务…

备忘录删除了怎么恢复?备忘录失而复得,掌握这3招!

备忘录是我们手机中的秘密花园&#xff0c;守护着每一个重要的思绪、待办事项与未来规划。它们不仅是日常工作的得力助手&#xff0c;更是心灵慰藉的小角落。但有时候&#xff0c;一个不经意的滑动或点击&#xff0c;这些珍贵的笔记和计划可能就会消失。备忘录删除了怎么恢复&a…

jpeg转pdf,分享5种图片转PDF的方法!

在日常工作和学习中&#xff0c;将JPEG图片转换为PDF文件是一项常见的需求。无论是为了保持文件的清晰度&#xff0c;还是为了方便分享和打印&#xff0c;JPEG转PDF都是一项非常实用的操作。本文将分享五种不同的JPEG转PDF的方法&#xff0c;帮助大家轻松完成这一任务。 方法一…

百度搜索的RLHF性能优化实践

作者 | 搜索架构部 导读 本文大语言模型在未经标注的大量文本上进行预训练后&#xff0c;可能产生包含偏见、泄露隐私甚至对人类构成威胁的内容。OpenAI 最先提出了基于人类反馈的强化学习算法(Reinforcement Learning fromHuman Feedback, RLHF)&#xff0c;将人类偏好引入到…

五种多目标优化算法(MOAHA、NSGA2、NSGA3、SPEA2、MODA)性能对比,包含47个多目标测试函数,6种评价指标,MATLAB代码

一、五种多目标算法及六种评价指标简介 NSGA-III&#xff1a; NSGA-III是Deb在2013年提出的&#xff0c;用于解决高维多目标优化问题。它采用参考点基于的非支配排序方法&#xff0c;并引入了种群的自适应标准化和关联操作&#xff0c;以提高算法在高维问题上的性能和多样性 。…

线程 --- 同步与生产消费者模型

序言 在上一篇的内容中&#xff0c;我们学习了使用互斥锁来保护共享资源&#xff0c;避免多个线程竞争&#xff0c;造成数据不一致等问题。在这一篇文章中&#xff0c;我们将继续深入&#xff0c;学习多线程同步以及生产消费者模型。 1. 线程同步 1.1 什么是线程同步 线程互斥…

操作系统常见面试题总结

文章目录 1 操作系统基础1.1 什么是操作系统&#xff1f;1.2 操作系统主要有哪些功能&#xff1f;1.3 用户态和内核态1.3.1 什么是用户态和内核态&#xff1f;1.3.2 为什么要有用户态和内核态&#xff1f;只有一个内核态不行么&#xff1f;1.3.3 用户态和内核态是如何切换的&am…

HICOOL 2024全球创业大赛角出200个获奖项目

近日&#xff0c;经过超过200天的紧张竞争&#xff0c;HICOOL 2024全球创业大赛从124个国家和地区的7406个创新项目中脱颖而出&#xff0c;共选出了200个获奖项目。 其中&#xff0c;“新一代智能光学显微成像仪器与全流程解决方案”和“基于多尺度深度学习的功能型生物分子设…