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

凡科建网站网站建设的方案模板下载

凡科建网站,网站建设的方案模板下载,asp网站开发培训,餐饮品牌设计公司排行榜前言 本文将会向你介绍互斥的概念#xff0c;如何加锁与解锁#xff0c;互斥锁的底层原理是什么 线程ID及其地址空间布局 每个线程拥有独立的线程上下文#xff1a;一个唯一的整数线程ID, 独立的栈和栈指针#xff0c;程序计数器#xff0c;通用的寄存器和条件码。 和其…前言 本文将会向你介绍互斥的概念如何加锁与解锁互斥锁的底层原理是什么 线程ID及其地址空间布局 每个线程拥有独立的线程上下文一个唯一的整数线程ID, 独立的栈和栈指针程序计数器通用的寄存器和条件码。 和其他线程共享的进程上下文的剩余部分整个用户虚拟地址空间那就是上图的数据段堆以及所有的共享库代码和数据区域也共享所有打开文件的集合。 pthread_create函数会产生一个线程id存放到第一个参数指向的地址中如果你将这个id打印出来会发现特别大其实这串数字是一个地址这个地址就是一个虚拟地址这样在主线程产生的临时数据都压在系统栈上而其他线程则存储在pthread库提供的栈内。 这里要注意的是线程的寄存器的内容是不共享的通常栈区是被相应线程独立访问的但是还是可能出现一个线程去访问另一个线程中的栈区的情况。如果这个线程获得了指向另一个线程栈区的指针那么它就可以读写这个栈的任何部分。 互斥相关概念 临界资源多线程执行流共享的资源就叫做临界资源 临界区每个线程内部访问临界资源的代码就叫做临界区 互斥任何时刻互斥保证有且只有一个执行流进入临界区访问临界资源通常对临界资源起保护作用 原子性后面讨论如何实现不会被任何调度机制打断的操作该操作只有两态要么完成要么未完成 互斥量 大部分情况线程使用的数据都是局部变量变量的地址空间在线程栈空间内这种情况变量归属单个 线程其他线程无法获得这种变量。 但有时候很多变量都需要在线程间共享这样的变量称为共享变量可以通过数据的共享完成线程之 间的交互。 多个线程并发的操作共享变量会带来一些问题。 模拟抢票 #include iostream #include cstdio #include cstring #include vector #include unistd.h #include pthread.h using namespace std; #define NUM 4 class threadData { public://构造函数threadData(int number){threadname thread- to_string(number);} public:string threadname; //线程名 }; int tickets 1000; void* getTicket(void *args) {//安全类型转换threadData *td static_castthreadData *(args);const char *name td-threadname.c_str();while(tickets){if(tickets 0){ usleep(10000);printf(who%s, get a ticket: %d\n, name, tickets);tickets--; }else break;}printf(%s ... quit\n, name);return nullptr; }int main() {vectorpthread_t tids;vectorthreadData * thread_datas;for(int i 1; i NUM; i){pthread_t tid;//构造一个对象指针threadData *td new threadData(i);//存放对象指针thread_datas.push_back(td);//创建线程将对象指针作为参数传递给getTicketpthread_create(tid, nullptr, getTicket, thread_datas[i-1]);//管理线程idtids.push_back(tid);}//线程等待for(auto thread : tids){pthread_join(thread, nullptr);}for(auto td : thread_datas){delete td;}return 0; }现象明明存在对tickets的条件判断可是票数依旧被抢到了负数 原因是多个线程可能同时检查tickets大于0然后同时减少tickets的值。这可能导致tickets的值减少到负数因为每个线程都可以执行tickets–操作即使tickets已经为0。 从底层来看 Ticket–这一步骤在汇编上是三条代码 1、先将tickets读入到cpu的寄存器中 2、cpu内部进行–操作 3、将计算结果的数据写回内存 举个例子 引入一个概念线程在执行的时候将共享数据加载到CPU寄存器的本质把数据的内容变成了自己的上下文—以拷贝的方式给自己单独拿了一份也就是说会将数据保存到自己的上下文当中 1、当执行线程一的时候倘若线程一刚执行完第一步就被切走 2、假设线程2一直能执行完3个步骤重复执行没有被中断最终票数被减到10了当刚要执行第一步骤的时候此时被切换此时将减到10的数据保存到自己的上下文当中 3、切换到线程一并不是紧接着执行第二步而是恢复自己的上下文数据1000到CPU当中它认为数据是1000最后将计算出来的999写回内存此时线程二先前将票数减到10的工作白做了 4、而此时如果再次切换到线程二线程二再将内存中的tickets读取到寄存器当中票数就又变成了999因此可以看出多个线程并发的操作共享变量会带来一些问题是线程切换导致的 我们也可以看出无论是–还是其实都不是原子性的因为它们会在cpu调度是被打断。 互斥锁 为了解决上述抢票的问题共享数据被读哦现场并发访问造成数据不一致的问题 需要做到三点 代码必须要有互斥行为当代码进入临界区执行时不允许其他线程进入该临界区。 如果多个线程同时要求执行临界区的代码并且临界区没有线程在执行那么只能允许一个线程进入该临界区。 如果线程不在临界区中执行那么该线程不能阻止其他线程进入临界区。 要做到这三点本质上就是需要一把锁。Linux上提供的这把锁叫互斥量。 加锁模拟抢票 引入函数接口 互斥锁 方法1静态分配 pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER方法2动态分配: int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 参数 mutex要初始化的互斥量 attrNULL销毁互斥量需要注意 使用 PTHREAD_ MUTEX_ INITIALIZER 初始化的互斥量不需要销毁 不要销毁一个已经加锁的互斥量 已经销毁的互斥量要确保后面不会有线程再尝试加锁 互斥量加锁和解锁 int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); 返回值:成功返回0,失败返回错误码调用 pthread_ lock 时可能会遇到以下情况: 互斥量处于未锁状态该函数会将互斥量锁定同时返回成功 发起函数调用时其他线程已经锁定互斥量或者存在其他线程同时申请互斥量但没有竞争到互斥量那么pthread_lock调用会陷入阻塞(执行流被挂起)等待互斥量解锁。 #include iostream #include cstdio #include cstring #include vector #include unistd.h #include pthread.h using namespace std; #define NUM 4class threadData { public://构造函数threadData(int number, pthread_mutex_t *mutex){threadname thread- to_string(number);lock mutex;} public:string threadname; //线程名pthread_mutex_t *lock; }; int tickets 500; void* getTicket(void *args) {//安全类型转换threadData *td static_castthreadData *(args);const char *name td-threadname.c_str();while(true){//上锁pthread_mutex_lock(td-lock); if(tickets 0){ usleep(1000);printf(who%s, get a ticket: %d\n, name, tickets);tickets--; pthread_mutex_unlock(td-lock);}else{//解锁pthread_mutex_unlock(td-lock);break;}}printf(%s ... quit\n, name);return nullptr; }int main() {vectorpthread_t tids;vectorthreadData * thread_datas;pthread_mutex_t lock;//初始化锁pthread_mutex_init(lock, nullptr);for(int i 1; i NUM; i){pthread_t tid;//构造一个对象指针threadData *td new threadData(i, lock);//存放对象指针thread_datas.push_back(td);//创建线程将对象指针作为参数传递给getTicketpthread_create(tid, nullptr, getTicket, thread_datas[i-1]);//管理线程idtids.push_back(tid);}//线程等待for(auto thread : tids){pthread_join(thread, nullptr);}for(auto td : thread_datas){delete td;}return 0; } 现象上锁了但是票数都是由一个线程抢走了 为什么会有这样的现象呢 故事时间 在纯互斥环境里如果锁分配不够合理容易导致其它线程的饥饿问题 比如存在一个独立自习室规矩出去后必须把钥匙放到指定的位置。倘若自习室里的人需要去吃饭然后出门看到一大堆人在等他出来然后他又进去了因为他不想失去这把但是由于他距离门更近一些因此他对钥匙的竞争更强一些 我们应该对此再加一个规矩出来的人不能立马重新申请锁想要继续申请必须排到队列的最后面外面来的必须排队 了解上述的故事之后我们可以对代码进行如下修改 互斥量实现原理探究 为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令,该指令的作用是把寄存器和内存单元的数据相交换,由于只有一条指令,保证了原子性,即使是多处理器平台,访问内存的总线周期也有先后,一个处理器上的交换指令执行时另一个处理器的交换指令只能等待总线周期。 现在我们把lock和unlock的伪代码改一下 1、当线程切换时线程要把它的上下文数据带走即把在寄存器中的值拷贝一份还要记录执行到哪一个位置了 2、当线程一执行完第一步就被切换首先把0保存到自己的上下文当中回来的时候要执行xchgb 3、 线程二来了把0mov到寄存器里让后与内存中的mutex1作交换此时内存中的值为0cpu寄存器的值为1当正要做判断的时候被切换了线程二要把寄存器中的内容带走并记录即将执行if语句 4、线程一回来了首先要恢复上下文数据将0又恢复到寄存器里然后执行交换发现 跟内存交换完后依旧是0 5、原因是线程二已经拿走了1线程一申请锁失败不会被调度线程二再恢复寄存器中的数据继续进行判断大于0申请锁成功 锁本身就是共享资源放在内存里这个数据仅有一把锁就是被所有线程共享的 此时持有锁的线程再将mutex中的值此时为0与1交换 小结 今日的分享就到这里啦如果本文存在疏漏或错误的地方还请您能够指出
http://www.pierceye.com/news/142818/

相关文章:

  • 网站建设论证方案传媒的域名做个什么网站
  • 成都建设网站企业电话国内信息图制作网站有哪些
  • 网站 图片切换wordpress永久免费
  • 自建社区网站网站建设全包设计
  • 广东装饰网站建设建设银行官网网站人事
  • 做网站设计赚钱吗保定模板建站平台
  • 找个免费网站这么难吗做球形全景的网站
  • c语言做网站后端深圳商业网站建设哪家好
  • wordpress小说网站模板下载地址网站建设中企动力推荐
  • 自己做网站网页剧中中国科技
  • 石家庄网站制作福州怎么提升网站打开速度
  • 网站分布郴州建设网站公司
  • 最有效的网站推广费用seo推广是什么意怿
  • 网站推广的基本方法是网站建设公司的介绍
  • 网站开发企业部门网站按抓取手机软件贵阳
  • 龙岗做网站公司icxun临夏州建设网站
  • 网站跳转到另外一个网站怎么做品牌推广部的职责
  • 视频网站开发用什么服务器wordpress数据库邮箱
  • 网站建设公司前十名电子商务网站建设论文开题报告
  • 泉州公司建设网站秦皇岛市网站建设
  • 网站建设说课获奖视频小程序制作用华网天下优惠
  • 杭州网站建设公司代理加盟广东建设企业网站怎么样
  • 网站建制作公司企业营销
  • 建设网站基本流程佛山制作网页公司
  • 眼睛网站开发wordpress影院插件
  • 成都专业做网站的公司有哪些建设工程管理专业
  • 北京seo关键词优化外包网站seo诊断分析报告
  • 怎么做淘宝客网站注册域名后如何建立网站
  • 网络营销资讯网站茶山镇仿做网站
  • 东莞产品网站建设网络设计方案包括哪些