贵阳网站建设多点互动创业it外包公司

pingmian/2025/10/15 9:43:41/文章来源:
贵阳网站建设多点互动,创业it外包公司,wordpress+move插件,企业免费建网站一、进程线程间通信的相关概念 临界资源#xff1a;多线程执行流共享的资源就叫做临界资源。确切的说#xff0c;临界资源在同一时刻只能被一个执行流访问。临界区#xff1a;每个线程内部#xff0c;访问临界资源的代码#xff0c;就叫做临界区。互斥#xff1a;通过互…一、进程线程间通信的相关概念 临界资源多线程执行流共享的资源就叫做临界资源。确切的说临界资源在同一时刻只能被一个执行流访问。临界区每个线程内部访问临界资源的代码就叫做临界区。互斥通过互斥操作能够保证在任何时刻有且只有一个执行流进入临界区访问临界资源通常对临界资源起保护作用。原子性不会被任何调度机制打断的操作该操作只有两态要么完成要么未完成 二、互斥锁 2.1 竞态条件 大部分情况线程使用的数据都是局部变量变量存储在线程栈空间内。这种情况变量归属单个线程其他线程无法访问这种变量。但有时候很多变量都需要在线程间共享这样的变量称为共享变量可以通过数据的共享完成线程之间的交互。比如全局数据、堆空间数据。多个线程并发的操作共享变量会带来数据竞争冲突以及数据不一致等竞态条件问题。 竞态条件 竞态条件Race Condition是指多个线程或进程同时访问共享资源并且对资源的访问顺序不确定导致最终结果的正确性依赖于线程执行的具体时序。竞态条件可能导致不可预测的结果破坏程序的正确性和一致性。竞态条件通常发生在多个线程或进程同时对共享资源进行读写操作时其中至少一个是写操作。当多个线程或进程同时读写共享资源时由于执行顺序的不确定性可能会导致数据的不一致性、丢失、覆盖等问题。 测试程序 int tickets 100; //共有100张票void *ThreadRoutine(void *name) {while (1){if (tickets 0){usleep(rand() % 1000); // 模拟业务过程花费的时间printf(%s sells ticket:%d\n, (char *)name, tickets);--tickets;}else{break;}usleep(rand() % 1000); // 模拟处理其他业务花费的时间}return nullptr; }int main() {srand((unsigned)time(nullptr));pthread_t tid1, tid2, tid3, tid4;pthread_create(tid1, nullptr, ThreadRoutine, (void *)child thread 1);pthread_create(tid2, nullptr, ThreadRoutine, (void *)child thread 2);pthread_create(tid3, nullptr, ThreadRoutine, (void *)child thread 3);pthread_create(tid4, nullptr, ThreadRoutine, (void *)child thread 4);pthread_join(tid1, nullptr);pthread_join(tid2, nullptr);pthread_join(tid3, nullptr);pthread_join(tid4, nullptr);return 0; }运行结果 同一编号的票被多个线程售出某些线程售出了负数编号的票 该程序存在竞态条件问题即公共变量tickets被多执行流同时访问和修改。 提示除了多线程进程外信号处理函数也是异步执行的多执行流执行同样存在竞态条件问题。 并发运行问题 例如tickets 0和--tickets操作并不是原子性操作而是对应三条汇编指令 将数据从内存加载到寄存器当前线程的上下文中进行逻辑运算或算数运算将数据写回内存 在这三条步骤的其中任何一步该线程都有可能被切换切换前线程上下文会被保存。其他线程在执行时也对tickets进行了访问和修改。当原线程再次被CPU调度执行时恢复上下文数据此时的寄存器与内存就会发生数据不一致的错误。 并行运行问题 多核CPU允许多线程并行同时运行。在ThreadRoutine函数中由于没有对访问tickets的操作进行互斥可能会导致多个线程同时读取和修改tickets变量从而产生不可预测的结果。 例如当多个线程同时执行if (tickets 0)语句时可能会出现以下情况 线程A和线程B同时读取tickets的值为1。线程A先执行--tickets操作将tickets的值减为0。线程B再执行--tickets操作将tickets的值减为-1。 这样就会出现某些线程售出了负数编号的票。 2.2 互斥锁的基本用法 为了解决竞态条件问题可以使用互斥锁Mutex来保护对tickets变量的访问。互斥锁可以确保在同一时间只有一个线程能够访问临界区对tickets变量的访问从而避免数据竞争的发生。 下面是互斥锁的基本使用方法 定义互斥锁变量在使用互斥锁之前需要先定义一个互斥锁变量。可以使用pthread_mutex_t类型来声明互斥锁变量例如pthread_mutex_t mutex;初始化互斥锁在使用互斥锁之前需要对互斥锁进行初始化。 静态初始化在定义互斥锁变量时使用PTHREAD_MUTEX_INITIALIZER宏进行初始化。动态初始化可以使用pthread_mutex_init函数来初始化互斥锁例如pthread_mutex_init(mutex, NULL);。第一个参数是要初始化的互斥锁变量第二个参数是互斥锁的属性通常使用NULL表示使用默认属性 加锁在访问共享资源之前需要先加锁。可以使用pthread_mutex_lock函数来加锁例如pthread_mutex_lock(mutex);。如果互斥锁已经被其他线程锁定那么当前线程会被阻塞直到互斥锁被解锁。访问共享资源在互斥锁被锁定的情况下可以安全地串行访问共享资源。解锁在访问共享资源完成后需要解锁互斥锁以便其他线程可以继续访问共享资源。可以使用pthread_mutex_unlock函数来解锁例如pthread_mutex_unlock(mutex);。销毁互斥锁 不再需要使用互斥锁时需要将其销毁。可以使用pthread_mutex_destroy函数来销毁互斥锁例如pthread_mutex_destroy(mutex);。静态初始化的互斥锁在程序结束时会自动被系统回收无需手动销毁。不要销毁一个已经加锁的互斥量对于已经销毁的互斥量要确保后面不会有线程再尝试加锁 我们将上面的售票程序加入互斥锁 int tickets 100; //临界资源 // 定义一个全局的互斥锁变量并利用宏进行初始化静态初始化 pthread_mutex_t mtx PTHREAD_MUTEX_INITIALIZER;void *ThreadRoutine(void *name) {while (1){// 在访问共享资源之前需要先加锁。pthread_mutex_lock(mtx);//临界区if (tickets 0){usleep(rand() % 1000); // 模拟业务过程花费的时间printf(%s sells ticket:%d\n, (char *)name, tickets);--tickets;// 在访问共享资源完成后需要解锁互斥锁。pthread_mutex_unlock(mtx);}else{// 在访问共享资源完成后需要解锁互斥锁。pthread_mutex_unlock(mtx);break;}// 在此处解锁不行如果线程执行break就不会解锁互斥锁。其他线程会被一直阻塞。usleep(rand() % 1000); // 模拟处理其他业务花费的时间}return nullptr; }运行结果 需要注意的几点 在访问共享资源完成后需要解锁互斥锁。否则其他线程会被一直阻塞。需要特别注意break, goto等跳转语句跳过解锁函数。 被互斥锁锁定的临界区只能串行执行互斥访问虽然保证了多执行流访问临界资源的安全性但是会在一定程度上降低程序的效率。 尽量保证被互斥锁锁定的代码都是访问临界资源的代码不要将其他无关的操作也放入临界区中。因为相比并发或并行执行临界区串行执行的效率较低。 再次改进上面的代码 #define THREAD_NUM 5 int tickets 100;//声明一个ThreadData类使线程入口函数的参数更多样化。 class ThreadData { public:string _tname; //线程名pthread_mutex_t *_pmtx; //互斥锁变量的地址ThreadData(const string tname, pthread_mutex_t *pmtx): _tname(tname),_pmtx(pmtx){}; };void *ThreadRoutine(void *arg) {ThreadData *td (ThreadData *)arg;while (1){// 在访问临界资源前进行加锁pthread_mutex_lock(td-_pmtx);if (tickets 0){usleep(rand() % 1000); // 模拟业务过程花费的时间printf(%s sells ticket:%d\n, td-_tname.c_str(), tickets);--tickets;// 不再访问临界资源时需要解锁。pthread_mutex_unlock(td-_pmtx);}else{// 不再访问临界资源时需要解锁。pthread_mutex_unlock(td-_pmtx);break;}usleep(rand() % 1000); // 模拟处理其他业务花费的时间}delete td; // 释放各自的ThreadData结构空间return nullptr; }int main() {srand((unsigned)time(nullptr));// 在主线程栈区创建互斥锁变量pthread_mutex_t mtx;// 调用pthread_mutex_init初始化互斥锁动态初始化pthread_mutex_init(mtx, nullptr);// 循环创建子线程pthread_t tid[THREAD_NUM];for (int i 0; i THREAD_NUM; i){string tmp child thread ;tmp to_string(i 1);ThreadData *td new ThreadData(tmp, mtx);pthread_create(tid i, nullptr, ThreadRoutine, td); //传入ThreadData对象的指针}// 循环等待子线程for (int i 0; i THREAD_NUM; i){pthread_join(tid[i], nullptr);}// 在不再需要使用互斥锁时需要将其销毁。动态初始化的互斥锁需要进行销毁而静态初始化不需要pthread_mutex_destroy(mtx);return 0; }新的问题 加锁了之后线程在执行临界区代码时是否会被切换会有问题吗? 会被切换但不会有问题虽然被切换了但是你是持有锁被切换的, 所以其他抢票线程要执行临界区代码也必须先申请锁而它是无法申请成功的。所以也不会让其他线程进入临界区就保证了临界区中数据一致性 对于访问临界资源的线程而言临界区代码要么全部执行成功要么全部不执行访问临界资源的操作不可被中断不能同时执行其他线程的临界区代码这就是原子性的体现。 要访问临界资源每一个线程都必须先申请锁而锁本身就是一种共享资源那么谁来保证锁的安全呢 所以为了保证锁的安全申请和释放锁必须是原子的 2.3 互斥锁的原理 在汇编层面一条汇编语句要么已经执行完要么就还没有执行是原子性的。为了实现互斥锁操作大多数体系结构都提供了swap或exchange汇编指令该指令的作用是把寄存器和内存单元的数据相交换由于只有一条指令保证了原子性。即使是多处理器平台并行访问内存的总线周期也有先后一个处理器上的交换指令执行时另一个处理器的交换指令只能等待总线周期。CPU的寄存器数据本质就是当前执行流的上下文。寄存器的存储空间被所有执行流共享但是寄存器的内容是被每一个执行流私有的。所以在切换线程时要将当前线程的寄存器数据保存到其PCB中并恢复下一个线程的寄存器数据。 以下是加锁的核心汇编伪代码 lock:movb $0, %al // 将数值0move到al寄存器中xchgb %al, mutex //交换al寄存器与mutex变量内存的数据if(al寄存器的内容 0){return 0;}else挂起等待;goto lock; //跳转到lock标签再次申请锁我们可以将互斥锁变量mutex理解成一个整形变量值为1表示互斥锁未被线程持有值为0表示互斥锁已经被其他线程锁定。创建互斥锁变量并进行初始化后其默认值为1。由于exchange汇编指令是原子的所以不管线程如何切换只有一个线程能够将mutex内存中的1值交换到自己的寄存器当中即该线程的上下文中。而线程上下文是线程的私有数据实现了公有到私有的转换。同时寄存器当中的0值被交换到了mutex中其他线程再进行交换也只能交换到0。在进行if判断时交换到1值的线程执行return 0可以安全地进入临界区访问临界资源而交换到0值的线程阻塞等待直到互斥锁被解锁这些线程才会被唤醒然后再次尝试申请锁。 以下是解锁的核心汇编伪代码 unlock:movb $1, mutex //将数值1move到mutex变量内存唤醒等待mutex的线程;return 0;当持有锁的线程访问完临界资源后会将mutex变量重新置为1即解锁互斥锁。同时应该唤醒等待互斥锁解锁的线程让他们再次竞争申请锁。 回答之前的问题 谁来保证锁的安全呢 为了保证锁的安全申请和释放锁必须是原子的在设计加锁时通过一条原子性的exchange指令保证了加锁和解锁的原子性。 加锁了之后线程在临界区中是否会切换会有问题吗? 线程在临界区中也可能会被切换但他是持有锁被切换的所谓持有锁切换是指互斥锁的1值保存在当前线程的上下文被当前线程私有。而其他线程即使被CPU调度执行也无法抢占互斥锁也就无法访问临界区代码。所以不会有任何问题。 三、可重入函数和线程安全 可重入函数同一个函数被多个执行流同时进入就叫重入。如果该函数在被重入执行的过程中不会出现任何错误则被称为可重入函数。反之就是不可重入函数。线程安全多个线程并发执行时在没有锁保护的情况下访问了共享资源如全局或静态变量堆区数据等会出现数据竞争从而导致数据冲突数据不一致等线程安全问题。 3.1 线程安全的情况 仅使用本地局部数据或者通过制作全局数据的本地拷贝来保护全局数据。使用互斥锁Mutex来保护对共享资源的访问。互斥锁可以确保在同一时间只有一个线程能够访问临界区从而避免数据竞争的发生。每个线程对共享资源只有读取的权限而没有写入的权限一般来说这些线程是安全的。不调用线程不安全的函数 3.2 可重入函数的情况 仅使用本地局部数据或者通过制作全局数据的本地拷贝来保护全局数据。使用互斥锁Mutex来保护对共享资源的访问。如全局、静态变量或其他共享资源。不调用不可重入函数 常见不可重入的情况 调用了malloc/free函数因为Linux内核是用全局链表和全局红黑树结构来组织和管理堆空间的。请看提示调用了标准I/O库函数因为标准I/O库的很多实现都以不可重入的方式使用了全局数据结构。 提示 关于Linux内核中的堆区管理请阅读【多线程】线程的概念 {Linux内核中的堆区管理虚拟地址到物理地址的转换页页框页表MMU内存管理单元Linux线程概念轻量级进程线程共享进程的资源线程的优缺点线程的用途}-CSDN博客关于多执行流调用不可重入函数插入链表节点请阅读【信号】信号处理 {信号处理的时机内核态和用户态信号捕捉的原理信号处理函数signal, sigaction可重入函数volatile关键字SIGCHLD信号}-CSDN博客 3.3 区别和联系 联系 函数是可重入的那就是线程安全的。函数是不可重入的那就不能由多个线程使用有可能引发线程安全问题。 区别 可重入函数是线程安全函数的一种。线程安全不一定是可重入的而可重入函数则一定是线程安全的。如果将对临界资源的访问加上锁则这个函数是线程安全的。但如果这个重入函数加锁还未释放则会产生死锁因此是不可重入的。 四、死锁 死锁Deadlock是指在并发系统中两个或多个进程或线程因为互相等待对方释放资源而无法继续执行的状态。在死锁状态下进程无法前进也无法释放资源导致系统无法正常运行。 死锁通常发生在多个进程或线程同时竞争有限的资源时每个进程都在等待其他进程释放资源而自己又无法释放已经占有的资源。 特殊情况一个执行流一把互斥锁也可能导致死锁即加锁后不解锁再次申请锁。 死锁的发生需要满足以下四个条件也被称为死锁的必要条件 互斥条件一个资源每次只能被一个执行流使用不加锁自然就不会产生死锁。 请求与保持条件一个执行流因请求资源而阻塞时对已获得的资源保持不放。 不剥夺条件一个执行流已获得的资源在未使用完之前不能强行剥夺。 循环等待条件若干执行流之间形成一种头尾相接的循环等待资源的关系使得每个执行流都在等待下一个执行流所占有的资源。 当这四个条件同时满足时就可能发生死锁。一旦发生死锁系统将无法自动解除死锁状态需要通过人工干预来解决。 为了避免死锁的发生可以采取以下策略 破坏互斥条件例如允许多个进程或线程同时访问某些资源。 破坏请求与保持条件例如要求进程或线程在执行之前一次性获取所有需要的资源否则在等待资源时释放已经占有的资源。 破坏不可剥夺条件例如允许系统强制剥夺某些进程或线程的资源。 破坏循环等待条件例如通过对资源进行排序按照固定的顺序申请资源避免交叉申请循环等待。T1,T2都先申请R1再申请R2 其他方法精简临界区代码缩短持有锁的时间合并临界区资源一次性分配一把锁 死锁是并发系统中的一个重要问题对系统的性能和可靠性有很大影响。因此在设计和实现并发系统时需要合理地分配和管理资源以避免死锁的发生。

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

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

相关文章

网站搭建平台都有哪些wordpress判断为空

(写于20200519) Tushare金融大数据社区 免费提供各类金融数据和区块链数据。我学python的动力之一就是使用金融数据进行量化投资。 原以为安装thshare是很容易的事,在cmd窗口输入pip install tushare后,似乎安装没报错&#xff0c…

内蒙古银税贷互动平台seo是指搜索引擎优化

不能制定脱离实际的法度,否则就是恶法,不可操作,事与愿违。转载于:https://www.cnblogs.com/jcode/p/6514698.html

呢图网品牌网络seo方案外包

怎样编写测试类测试分支很难为干净的代码找到一个好的定义,因为我们每个人都有自己的单词clean的定义。 但是,有一个似乎是通用的定义: 简洁的代码易于阅读。 这可能会让您感到有些惊讶,但我认为该定义也适用于测试代码。 使测试…

安新seo优化排名网站h5制作官网

目录 一.设计一个类,不能被拷贝 二.设计一个类只能在堆上创建对象 三.设计一个类只能在栈上创建对象 四. 请设计一个类,不能被继承 五.请设计一个类,只能创建一个对象(单例模式) 1.单例模式: 2. 饿汉模式 一.设计一个类&#x…

外贸视频网站wordpress模版哪个好

sysbench 是一个非常经典的综合性能测试工具,通常都用它来做数据库的性能压测,但也可以用来做CPU,IO的性能测试。而对于IO测试,不是很推荐sysbench,倒不是说它有错误,工具本身没有任何问题,它的…

什么软件做网站最好怎么让自己的网站通过域名访问不了

nohup 是一个 POSIX 命令,它的名称来源于“no hang up”的缩写。这个命令的基本用途是运行一个命令,使得该命令在用户登出或者终端关闭后继续运行。nohup 命令通常与后台运行的命令(使用 & 符号)结合使用,以便在终…

中国建设教育网官方网站企业信息化建设如何帮助客户理解网站流量

卓里奇书好的一点就是,不是直接引出公式,而是告诉你理由。先引出正交的概念,然后在函数空间中,也有正交,只不过是无限维的空间。 这里要注意,明确说明了是有限个。 在函数空间里面,内积是指进行…

商务网站建设工程师如何帮人做网站赚钱吗

目录 引出nacos服务器和命名空间Nacos服务器命名空间 springBoot整合nacosspringcloud Alibaba 版本与springcloud对应关系引包配置maincontroller 报错以及解决【报错】错误:缺少服务名称报错:9848端口未开放 启动测试引入多个nacos配置多个配置的情况没…

襄阳专业做网站想学网站开发

一、数学运算类 abs(x) 求绝对值 1 、参数可以是整型,也可以是复数 2 、若参数是复数,则返回复数的模 complex([real[, imag]]) 创建一个复数 divmod(a, b) 分别取商和余数 注意:整型、浮点型都可以 float([x]) 将一个字符串或数转换为浮点数…

做一个企业网站设计长春网站建设那家好

C入门 文章目录 C入门框架命名空间 namespace &#xff08;不常用&#xff09;命名空间的使用方式&#xff08;三种&#xff09;using namespace std;\<iostream>coutendlcincout的使用命名冲突缺省参数&#xff08;省钱的省&#xff09;缺省参数分类全缺省参数半缺省参数…

小程序电商平台排名嘉兴做网站优化价格

TCL&#xff1a;花开刹那还是浴火重生 [url]http://www.sina.com.cn[/url] 2008年04月07日 15:24 民营经济报本报记者 叶键 TCL3月份公布了2007年财报&#xff0c;公司净利润达3.9亿元&#xff0c;并于3月27日“摘星脱帽”&#xff0c;恢复为“TCL集团”的自由身&#xff0c;…

网站建设总结ppt深圳做网站的公司的区域

1、效果 如下图所示&#xff0c;我们在输入大学时&#xff0c;程序会到后端查询名字中包含大学的数据&#xff0c;并展示到前端页面。 用户选择一个大学&#xff0c;该大学值会被赋值到input表单&#xff0c;同时关闭下拉表单&#xff1b; 当页面展示的数据都不符合条件时&…

安徽城乡住房建设厅网站网站建设預算

这里写目录标题 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真4. 实物烧录和现象5. 程序代码6. 设计资料内容清单&&下载链接资料下载链接&#xff1a; 【普中开发板】基于51单片机温度报警器设计( proteus仿真程序实物演示讲解视频&#xff09; Proteus 仿真…

个人网站可以收费吗网站建设源代码版权问题

大家好&#xff0c;我是若川。持续组织了近一年的源码共读活动&#xff0c;感兴趣的可以 加我微信lxchuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外&…

政务建设网站得必要性网站开发在线学习

通信框架功能设计 功能描述 通信框架承载了业务内部各模块之间的消息交互和服务调用&#xff0c;它的主要功能如下&#xff1a; 基于 Netty 的 NIO 通信框架&#xff0c;提供高性能的异步通信能力&#xff1b; 提供消息的编解码框架&#xff0c;可以实现 POJO 的序列化和反序…

泰和网站制作厦门网页建站申请费用

emlog默许不能生成静态文件&#xff0c;不过彷佛有生成静态页面的相干插件&#xff0c;该插件博客吧先不研讨&#xff0c;本日博客簿要引见的是emlog 4.0版本在IIS6环境下的伪静态划定规矩&#xff0c;人人都晓得&#xff0c;经由过程伪静态能够让博客文章网址变得对搜索引擎越…

ui设计的细分研究方向包含哪几项福州搜索优化网站

线程同步机制为线程协同工作而设计&#xff0c;windows系统中有多种机制可以用于线程同步&#xff0c;最常用的有下面几种&#xff1a; 互斥对象(Mutex)时间对象(Event)信号量(Semaphore)临界区(critical section)可等待计时器(waitable Timer)同步过程中两个重要的概念是同步对…

石家庄建设企业网站建设我们的网站

GPS北斗卫星同步时钟系统(北斗授时设备)在通信系统中应用 GPS北斗卫星同步时钟系统(北斗授时设备)在通信系统中应用 卫星时间同步系统是根据《华东电网统一时钟系统技术规范》、《上海电网GPS时间同步系统技术原则和运行管理规定》和《电力系统时间同步技术规范》设计的时间同步…

做平台的网站有哪些功能张店学校网站建设定制

最近在使用这几个在做项目&#xff0c;因为第一次用这个&#xff0c;所以不免有些问题。总结下踩的坑 1.测试类位置 首先测试类约定会放在tests里面&#xff0c;不然有可能发生引入包的问题&#xff0c;会报错某些包找不到。 2. 测试类依赖注入 这里我就用的真实的数据库操作…

学校网站群建设做采购 通常在什么网站看

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…