当前位置: 首页 > wzjs >正文

网站关键词字符编辑农产品网站如何做地推

网站关键词字符编辑,农产品网站如何做地推,北京网站建设开发公司哪家好,页面设计粉色好处文章目录 1. 互斥1.1 为什么需要互斥1.2 互斥锁1.3 初谈互斥与同步1.4 锁的原理1.5 可重入VS线程安全1.6 死锁1.7 避免死锁的算法(扩展) 序:在上一章中我们知道了线程控制的三个角度:线程创建、线程等待和线程终止,分别…

文章目录

      • 1. 互斥
        • 1.1 为什么需要互斥
        • 1.2 互斥锁
        • 1.3 初谈互斥与同步
        • 1.4 锁的原理
        • 1.5 可重入VS线程安全
        • 1.6 死锁
        • 1.7 避免死锁的算法(扩展)

  • 序:在上一章中我们知道了线程控制的三个角度:线程创建、线程等待和线程终止,分别从接口以及参数的意义和功能的角度来了解,以及最后深入原生线程库,了解用户级线程与内核轻量型进程的关系。而本章将从线程的同步与互斥的角度来带大家了解什么是互斥和同步,以及为什么要互斥和同步等一系列问题。

上一章线程控制的知识补充:

线程分离:
在这里插入图片描述
pthread_detach函数,可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离,分离后的线程不可被等待,如果强行等待也会返回错误码22。

问题一:为什么要有线程分离呢?

如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。

归根结底,我们让线程分离,其实就是更改线程的原生线程库里的tcb内的分离的属性,而pthread_join就是识别到了该分离属性被更改为已分离,所以才会直接返回一个错误码。

1. 互斥

1.1 为什么需要互斥

多线程抢票模型代码演示:

#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<string>
#include<vector>
using namespace std;#define NUM 4int ticket =100;//用多线程,模拟一轮抢票class ThreadData
{
public:ThreadData(int number){_thread_name ="thread-" + to_string(number);}
public:string _thread_name;
};void* GetTicket(void* args)
{ThreadData* td=static_cast<ThreadData*>(args);const char* name =td->_thread_name.c_str();while(true){if(ticket>0){usleep(5000);printf("i am %s,get a ticket:%d\n",name,ticket);ticket--;}else break;}printf("%s ... quit\n",name);return nullptr;}
int main()
{vector<pthread_t> tids;vector<ThreadData*> thread_datas;for(int i=0;i<NUM;i++){pthread_t tid;ThreadData* td=new ThreadData(i);thread_datas.push_back(td);pthread_create(&tid,nullptr,GetTicket,thread_datas[i]);tids.push_back(tid);}for(auto &e :tids){pthread_join(e,nullptr);}for(auto &e :thread_datas){delete e;}return 0;
}

结果如图:

在这里插入图片描述
那么问题来了抢票模型中,为什么抢票抢到最后,竟然抢到了负数?这个问题我们暂且不谈,我们继续往下说。

要想了解为什么会出现这样的情况,我们首先就要知道既然ticket出现了负数,就说明ticket–出现了问题,共享数据------>数据不一致问题!!!(肯定和多线程并发访问是有关系的),对一个全局变量进行多线程并发–或++操作是否是安全的?所以这个–操作不是原子的,所以也不是安全的。

既然–操作是不安全的,不是原子的,那我们要了解ticket–究竟要有哪些步骤:
在这里插入图片描述

第一个步骤:先将ticket读入到CPU的寄存器当中
第二个步骤:CPU内部进行–操作
第三个步骤:将计算结果写回内存

但是想要了解为什么会出现这样的情况,我们还要了解一个额外的知识点:寄存器不等于寄存器的内容线程在执行的时候,将共享数据,加载到CPU寄存器的本质:把数据的内容,变成了自己的上下文 — 这样的数据以拷贝的形式给自己单独拿了一份

既然ticket–是有三个步骤组成,如果在这三个步骤之内发生了线程切换就会导致数据不一致的问题!!!

在这里插入图片描述
假设当前抢票的进程中,票有1000张,该进程内有两个线程正在抢票,此时thread-1线程正在实现抢票,刚完成第一步,将内存中的数据读入寄存器中,也就是读入该线程的上下文中,如果此时来了第二个线程thread-2也要实行抢票,将thread-1线程切换了,thread-1线程就会带着这个1000的数据一起离开,等待线程再次切换回来!!!
在这里插入图片描述
当线程切换到thread-2线程,假设此时thread-2线程在下一次线程切换的时间片内进行了100次抢票的动作,此时的票数就由1000变成了900
在这里插入图片描述

当thread-2线程抢了100张票后,将寄存中的900写回给内存中的ticket,此时thread-1线程切换回来了,thread-2线程就要带着自己的硬件上下文走,于是thread-2就将寄存器中的900带走了,thread-1线程切换回来后,会将之前就带走的寄存器中的1000带回来,在放入到寄存器中,即恢复上下文。
在这里插入图片描述
然后,此时thread-1会继续执行未完成的动作,继续执行第二步和第三步。
在这里插入图片描述
这就会导致,thread-2辛辛苦苦抢的票,将1000变成900,结果thread-1线程切换回来后就变成了999。

现在让我们来回答最开始的那个问题,为什么ticket会出现负数?
在这里插入图片描述
假设此时的实际票数小于线程数,此时有四个线程,但票只有两个了,别忘了ticket>0也是运算(逻辑运算)所以此时同时有4个线程都对ticket进行了逻辑运算,此时票有两个,都是大于0,此时四个线程都进入了该循环内,都可以进行ticket–,这也就是为什么会出现了负数!!!

1.2 互斥锁

怎么解决上述的一些列问题???
对共享数据的任何访问,保证任何时候只有一个执行流进行访问!—互斥!!!
而想要实现互斥就要引入互斥锁的概念!!!

在这里插入图片描述

锁资源的定义,初始化和释放:

pthread_mutex_t是库提供的一种数据类型
pthread_mutex_init(第一个参数传锁,第二个参数传锁的各种参数(默认传nullptr))
pthread_mutex_destroy
(如果用pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALZER进行全局变量的初始化,就不用调用pthread_mutex_destroy函数进行释放)

一种临界资源,由多个线程访问,如果想要保证临界资源的安全,就必须让这个多个线程访问同一把锁!!!

在这里插入图片描述

锁的申请和释放:

pthread_mutex_lock
pthread_mutex_unlock
其中的pthread_mutex_trylock函数就是加锁的非阻塞版本

到这一步,大家只能对锁有个印象,没法深刻知道锁的作用和锁的使用,接下来我将改进原本的多线程抢票模型的代码,用互斥锁来使原版中的多线程导致的数据不一致问题得到解决!!!

互斥锁版的多线程抢票模型代码演示

#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<string>
#include<vector>using namespace std;#define NUM 5int ticket =100;//用多线程,模拟一轮抢票class ThreadData
{
public:ThreadData(int number,pthread_mutex_t* lock){_thread_name ="thread-" + to_string(number);_lock=lock;}
public:string _thread_name;pthread_mutex_t *_lock;
};void* GetTicket(void* args)
{ThreadData* td=static_cast<ThreadData*>(args);const char* name =td->_thread_name.c_str();while(true){pthread_mutex_lock(td->_lock);if(ticket > 0){//usleep(5000);printf("i am %s,get a ticket:%d\n",name,ticket);ticket--;}else{pthread_mutex_unlock(td->_lock);break;}pthread_mutex_unlock(td->_lock);usleep(5000);}printf("%s ... quit\n",name);return nullptr;
}int main()
{pthread_mutex_t lock;pthread_mutex_init(&lock,nullptr);vector<pthread_t> tids;vector<ThreadData*> thread_datas;for(int i=0;i<NUM;i++){pthread_t tid;ThreadData* td=new ThreadData(i,&lock);thread_datas.push_back(td);pthread_create(&tid,nullptr,GetTicket,thread_datas[i]);tids.push_back(tid);}for(auto &e :tids){pthread_join(e,nullptr);}for(auto &e :thread_datas){delete e;}pthread_mutex_destroy(&lock);return 0;
}

对于上面一段代码,我们用锁将临界资源锁住,同一时间只能有一个线程进行访问,从而实现对临界资源的保护

其中,被锁保护的资源叫做临界资源,某几段访问临界资源的代码区叫做临界区

加锁的本质:是用时间来换安全
加锁的表现:线程对临界区代码的串行执行
加锁原则:尽量保证临界区代码越少越好。
申请锁成功了,才能往后执行,不成功,就会阻塞等待(等待锁资源释放)

不同线程对于锁的竞争能力可能会不同,在纯互斥环境中,如果锁分配不够合理,容易导致其他线程的饥饿问题----->不是说只要有互斥就必有饥饿,适合纯互斥场景就用互斥。

1.3 初谈互斥与同步

目前,我们对于锁的概念已经有了一个清晰的认识了,但是我们发现了一个新的问题,当一个线程申请锁,完成对临界资源的访问后,释放锁后,该线程可能也会申请锁,这就可能出现一个线程一直在申请和释放锁,导致其他线程没办法申请到锁,对于这种情况,就要深入了解同步的概念来解决新出现的问题,现在让我们更加深入的了解互斥与同步吧

现在有一个vip自习室:
在这里插入图片描述
vip自习室规定:1. 外面的同学想要进入vip自习室必须排队。2. 出来的同学,将钥匙放好后,不能立马重新拿钥匙进vip自习室,如果想要再次进入自习室则必须排到队列的尾部进行排队

vip自习室的规则让所有的同学(线程)按照一定的顺序拿到钥匙(锁)进入vip自习室,而按照一定的顺序性获取资源的模式就是同步!!!

1.4 锁的原理

锁本身也是一种临界资源!!!所以。申请锁和释放锁本身就被设计成为了原子性操作了(问题:如何做到的???)

在临界区中,线程可以被切换吗?可以切换!!!在线程被切出去的时候,是持有锁被切走的。该线程即使被切换走了,照样没有任何线程能进入资源临界区访问临界资源!

对于其他线程来讲,一个线程要么没有锁,要么释放锁。当前线程访问临界区的过程,对于其他线程就是原子的!!!

问题一:为什么说ticket–不是原子的?因为该语句会变成多条汇编语句,在该汇编语句的中间,如果有其他线程也在执行,就会出错,出现不一致的情况,换言之,只要汇编语句只有一条就没有问题,所以,原子:只有一条汇编语句就是原子的!!!

lock的汇编语句:xchqb %al,mutex
Xchqb交换的本质:把内存中的数据(共享),交换到CPU的寄存器中(把数据交换到线程的硬件的上下文中)—>把一个共享的锁,让一个线程以一条汇编语句的方式,交换到自己的上下文中!!!(这就叫做当前线程持有锁了!!!)

unlock的汇编语句:movb $1,mutex:将一个共享的锁从线程的上下文中拿出来。(这就叫做当前线程释放锁了!!!)

1.5 可重入VS线程安全

线程安全的概念:多个线程并发同一段代码时,不会出现不同的结果。常见对全局变量或者静态变量进行操作, 并且没有有锁保护的情况下,会出现该问题。
重入的概念:同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们称之为重入。一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数被称为可重入函数、不则具不可重入函数。

可重入与线程安全联系:

函数是可重入的,那就是线程安全的。
函数是不可重入的,那就不能由多个线程使用,有可能引发线程安全问题。
如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。

可重入与线程安全区别:

可重入函数是线程安全函数的一种。
线程安全不一定是可重入的,而可重入函数则一定是线程安全的。
如果将对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会产生死锁,因此是不可重入的。

1.6 死锁

死锁的概念:

死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。

死锁产生的必要条件:

互斥条件:一个资源每次只能被一个执行流使用(前提)
请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放(原则)
不剥夺条件:一个执行流已获得的资源,在末使用完之前,不能强行剥夺(原则)
死锁产生的充分条件:
循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系(重要条件)
这三个必要条件必须同时满足才是死锁。

如何避免死锁问题?

1. 破坏死锁的四个必要条件,只需要一个不满足就可以了
2. 加锁顺序一致
3. 避免锁未释放的场景
4. 资源一次性分配

1.7 避免死锁的算法(扩展)

银行家算法:

下面是银行家算法的模拟实现,感兴趣的小伙伴可以去了解

银行家算法避免死锁

总结:

本篇博客先是补充了上一章中对于线程分离的知识缺失的内容补全,而后,从一小段代码出发,在多线程的抢票模型下,我们逐步发现多线程带来的问题,并逐步解决,为了解决这些问题,我们先后引入了互斥和同步的概念,最后有队线程安全问题和可重入的问题进行了了解,并讲述了死锁的概念及其产生的条件,最后以避免死锁的银行家算法结尾,谢谢大家的支持!!!


文章转载自:

http://lNAt0HGp.yzdth.cn
http://kCdWjrBc.yzdth.cn
http://rkHmvSwG.yzdth.cn
http://oPXpFeD4.yzdth.cn
http://ZOYsit7R.yzdth.cn
http://jqC4MhWM.yzdth.cn
http://9n0UrTH4.yzdth.cn
http://ohoFXjU2.yzdth.cn
http://CEG35jWQ.yzdth.cn
http://zAiK3ODZ.yzdth.cn
http://gro31efF.yzdth.cn
http://7mfSLYyy.yzdth.cn
http://fEkZ9UsV.yzdth.cn
http://NPifQTWH.yzdth.cn
http://Put2nVNn.yzdth.cn
http://Oht1RmgM.yzdth.cn
http://dnP7Eka1.yzdth.cn
http://tq5VyHDm.yzdth.cn
http://s1PvEJIo.yzdth.cn
http://v6ZvmGHW.yzdth.cn
http://tRXnX5fk.yzdth.cn
http://0DY3pasl.yzdth.cn
http://13ntDDs0.yzdth.cn
http://A7qX1HQS.yzdth.cn
http://DXEXE2sx.yzdth.cn
http://wSbb509t.yzdth.cn
http://oQSeHsyH.yzdth.cn
http://CWsbmsAM.yzdth.cn
http://cGM6EPaD.yzdth.cn
http://P8Owdpt5.yzdth.cn
http://www.dtcms.com/wzjs/647967.html

相关文章:

  • 安微凤阳县建设局网站六盘水城乡住房建设厅网站
  • 家具营销型网站模板重庆双福建设开发有限公司网站
  • 网站去哪里备案注册500万公司实缴多少钱
  • 温州网站 公司论坛网站开发外文文献
  • 网站推广教程分享帮公司做网站运营
  • ui设计师网站团购网站开发语言
  • 建筑工程分包平台优化网站哪家好
  • 邯郸做移动网站价格厦门品牌网站设计
  • 学校信息门户网站建设江苏建设外贸公司网站
  • 那种系统做网站比较好上海做网站的公司
  • 支持微信支付的网站开发室内空间设计
  • 电商网站有哪些特色qq空间如何发布wordpress
  • 上杭网站设计公司找别人建网站去哪里
  • 山东省建设局网站首页网站模块制作
  • 本地化网站建设网站建设零基础教材免费下载
  • 制作网站学什么专业开源cms建站
  • 网站改版优化果洛wap网站建设
  • 淄博市建设业协会网站万网 网站超市
  • 万户网站做的怎样网站建设服务器有哪些
  • yp77731域名查询福州网站建设方案优化
  • 建网站找兴田德润网上商城网站建设规划
  • 燕郊建设局网站国外做兼职网站设计
  • 国外有哪些网站做推广的比较好网站设计公司哪家好如何选择呀
  • 南宁营销型网站建设公司哪家好生鲜网站建设背景
  • 建瓯网站制作如何做企业产品推广
  • 小江网站建设公司统一门户网站建设规范
  • 谷歌收录网站网站自己怎么做直播
  • 珠海网站艰涩和合肥网站建设渠道
  • 临沂网站建设兼职优秀的网站建设解决方案
  • 做网站界面尺寸是多少答辩ppt模板下载免费完整版