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

管理网站怎么做的中国公司网站建设

管理网站怎么做的,中国公司网站建设,如何让百度搜索到自己的网站,页面模板怎么用并发编程–条件量与死锁及其解决方案 文章目录 并发编程--条件量与死锁及其解决方案1.条件量1.1条件量基本概念1.2条件量的使用 2. 死锁 1.条件量 1.1条件量基本概念 在许多场合中,程序的执行通常需要满足一定的条件,条件不成熟的时候,任务…

并发编程–条件量与死锁及其解决方案

文章目录

  • 并发编程--条件量与死锁及其解决方案
    • 1.条件量
      • 1.1条件量基本概念
      • 1.2条件量的使用
    • 2. 死锁

1.条件量

1.1条件量基本概念

在许多场合中,程序的执行通常需要满足一定的条件,条件不成熟的时候,任务应该进入睡眠阻塞等待,条件成熟时应该可以被快速唤醒。另外,在并发程序中,会其他任务同时访问该条件,因此任何时候都必须以互斥的方式对条件进行访问。条件量就是专门解决上述场景的逻辑机制。

注意,上述表述中,条件和条件量是两个不同的东西,所谓条件就是指程序要继续运行所需要的前提条件,比如文件是否读完、内存是否清空等具体的场景限定,而条件量(即pthread_cond_t)是本节课件要讨论的一种同步互斥变量,专用于解决上述逻辑场景。

img
条件量的逻辑

说明:

  1. 在进行条件判断前,先加锁(防止其他任务并发访问)
  2. 成功加锁后,判断条件是否允许
    • 若条件允许,则直接操作临界资源,然后释放锁
    • 若条件不允许,则进入条件量的等待队列中睡眠,并同时释放锁
  3. 在条件量中睡眠的任务,可以被其他任务唤醒,唤醒时重新判定条件是否允许程序继续执行,当然也是必须先加锁。

1.2条件量的使用

条件量一般要跟互斥锁(或二值信号量)配套使用,互斥锁提供锁住临界资源的功能,条件量提供阻塞睡眠和唤醒的功能。

一般流程示例
以取款为例,假设有多个任务可同时访问存款余额 balance,其中某个任务希望从中取出 ¥100 元,并且要求满足如下逻辑:

  • 如果余额中有大于等于100元,则立即取出
  • 如果余额小于100元,则进入睡眠等待
  • 当有别的任务修改了余额时可被唤醒,并继续判定是否可取款
pthread_mutex_t m;  // 互斥锁
pthread_cond_t  v;  // 条件量// 银行余额(全局变量,意味着有别的进程可随时访问)
extern int balance;int main()
{// 1,初始化pthread_mutex_init(&m, NULL);pthread_cond_init(&v, NULL);// 2,对m加锁pthread_mutex_lock(&m);// 2,当条件不允许时,进入条件量中睡眠//    进入睡眠时,会自动对m解锁//    退出睡眠时,会自动对m加锁while(balance < 100)pthread_cond_wait(&v, &m);// 3,取款balance -= 100;// 4,对m解锁pthread_mutex_unlock(&m);
}

其他任务,可以在适当的时候,通过如下接口来唤醒处于睡眠态的任务:

// 单个唤醒,唤醒第一个进入条件量中睡眠的任务
pthread_cond_signal(&v);// 集体唤醒,唤醒进入条件量中睡眠的所有任务
pthread_cond_broadcast(&v);

2. 死锁

死锁指的是由于某种逻辑问题,导致等待一把永远无法获得的锁的困境。比如最简单的是同一线程,连续对同一锁资源进行加锁,就进入了死锁。

img

最简单的死锁示例

pthread_mutex_t m;int main()
{pthread_mutex_init(&m, NULL);// 正常加锁pthread_mutex_lock(&m);// 未释放锁前重复加锁,进入死锁状态pthread_mutex_lock(&m);// 下面的代码永远无法执行......
}

以上死锁的例子,可以通过仔细检查代码得以避免,但在现实场景中,有些产生死锁的情况是无法避免的,比如如下情形:

一条线程持有一把锁,期间不能屏蔽取消指令
然后又恰巧被取消指令强制终止,此时死锁的产生变得不可避免。

产生死锁示例

void *routine(void *arg)
{thread_pool *pool = (thread_pool *)arg;struct task *p;while(1){// 操作临界资源之前,加锁pthread_mutex_lock(&pool->lock);// 条件不允许时,进入条件量等待while(pool->waiting_tasks == 0 && !pool->shutdown)pthread_cond_wait(&pool->cond, &pool->lock);// 条件允许时,操作临界资源p = pool->task_list->next;pool->task_list->next = p->next;pool->waiting_tasks--;// !!! 注意 !!!// 线程若恰好在此处被意外终止,将导致死锁// 解锁pthread_mutex_unlock(&pool->lock);// 其他操作pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);(p->do_task)(p->arg);pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);free(p);}pthread_exit(NULL);
}

上述代码中,若线程在中间被取消,则导致死锁。对于这种情况,一个可行的解决办法是:

  1. 提前准备一个解锁处理函数,并将其压入线程专用的函数栈中备用。
  2. 准备操作临界资源,加锁
  3. 操作临界资源
    • 重点:
    • 若线程在此期间意外终止,则会自动调用处理函数解锁
  4. 解锁
  5. 在函数栈中弹出处理函数

说明:
上述做法实际上相当于现实生活中的立遗嘱,因为人去世之后是无法再做任何事情的,因此为了防止死亡在关键阶段意外到来,可以在提前立遗嘱,万一不幸遇到该情况就有了预案(处理函数),但如果并未发生此种情形,那么就将遗嘱作废(弹出处理函数且不执行)即可。

根据以上思路,可将上述代码改良为如下代码:

// 意外处理函数:
// 自动解锁
void handler(void *arg)
{pthread_mutex_unlock((pthread_mutex_t *)arg);
}void *routine(void *arg)
{thread_pool *pool = (thread_pool *)arg;struct task *p;while(1){/*** push a cleanup functon handler(), make sure that** the calling thread will release the mutex properly** even if it is cancelled during holding the mutex.**** NOTE:** pthread_cleanup_push() is a macro which includes a** loop in it, so if the specified field of codes that ** paired within pthread_cleanup_push() and pthread_** cleanup_pop() use 'break' may NOT break out of the** truely loop but break out of these two macros.** see line 56 below.*///================================================//pthread_cleanup_push(handler, (void *)&pool->lock); // 提前准备好意外处理函数pthread_mutex_lock(&pool->lock);//================================================//// 1, no task, and is NOT shutting down, then waitwhile(pool->waiting_tasks == 0 && !pool->shutdown)pthread_cond_wait(&pool->cond, &pool->lock);// 2, no task, and is shutting down, then exitif(pool->waiting_tasks == 0 && pool->shutdown == true){pthread_mutex_unlock(&pool->lock);pthread_exit(NULL); // CANNOT use 'break';}// 3, have some task, then consume itp = pool->task_list->next;pool->task_list->next = p->next;pool->waiting_tasks--;//================================================//pthread_mutex_unlock(&pool->lock); pthread_cleanup_pop(0); // 弹出处理函数且不执行//================================================//pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);(p->do_task)(p->arg);pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);free(p);}pthread_exit(NULL);
}

注意:

  • pthread_cleanup_push() 用于将处理函数填入栈中,在线程意外终止后会被自动调用。
  • pthread_cleanup_pop() 用于将栈中的处理函数弹出,若参数为0则意味着不执行,参数不为零则意味着执行该函数。
  • pthread_cleanup_push()pthread_cleanup_pop() 必须成对出现。

文章转载自:

http://HTpaOh8L.cLkyw.cn
http://A7NtkOLQ.cLkyw.cn
http://rUlTeCCH.cLkyw.cn
http://nWXGwK3K.cLkyw.cn
http://waKzM2et.cLkyw.cn
http://bAVeUXkH.cLkyw.cn
http://DNHfaKVD.cLkyw.cn
http://hpHM23cv.cLkyw.cn
http://cQ8r928Q.cLkyw.cn
http://tfHnyIIK.cLkyw.cn
http://Zw7UfFhp.cLkyw.cn
http://rTbInEuT.cLkyw.cn
http://2PwPNMWn.cLkyw.cn
http://l4epsPlV.cLkyw.cn
http://hCsKde9e.cLkyw.cn
http://DaCzRmxn.cLkyw.cn
http://hAahykBH.cLkyw.cn
http://4kns0Fo5.cLkyw.cn
http://TFnHULwc.cLkyw.cn
http://N5pbBvOb.cLkyw.cn
http://gck9wF6s.cLkyw.cn
http://hTyVtCPi.cLkyw.cn
http://EXubRibI.cLkyw.cn
http://e4MuKfwe.cLkyw.cn
http://v30yljF8.cLkyw.cn
http://J2FibbY4.cLkyw.cn
http://6ioiwz3G.cLkyw.cn
http://Px9fgrCE.cLkyw.cn
http://RnR5uFoq.cLkyw.cn
http://abJYCKJK.cLkyw.cn
http://www.dtcms.com/wzjs/757195.html

相关文章:

  • 免费建站哪个网站最好网站注册页面html
  • 腾讯官方网站定制一个软件要多少钱
  • 网站建设地址北京昌平刷leetcode对网站开发有用吗
  • 制作微网站公司高港区住房和城乡建设局网站
  • 建造网站 备案wordpress 3.9中文版
  • 东莞网站建设 信科网络潍坊市城乡建设局网站
  • 网站设计的工作内容长沙百度公司地址
  • 北京网络电视台网页怎么优化
  • 从事网站建如何注册或购买一个域名使用
  • 如皋网站建设厦门网站推广费用
  • 免费网站空间怎么python零基础教程
  • 网站开发环境与工具免费网站建设ppt模板
  • 中国建设银行官方网站2018年年报辽宁省建设厅科技中心网站
  • 怎么做卖卷网站正保建设工程教育网官网
  • 黄石市下陆区建设管理局网站建站行业乱象完整版
  • 网站的404如何做wordpress中文采集插件
  • 网站功能开发水果网站建设的策划书
  • 可信网站标识宁波创建网站
  • 网站安全证书有问题如何解决怎么样注册自己的网站
  • 孝感网站建设 付款方式 银行中职示范校建设验收网站
  • 电话网站域名到期制作网站培训
  • 南宁网站建设王道下拉強wordpress注册公众号
  • 长沙口碑最好网站建设公司排行榜网站导航作用
  • 网站推广策划公司网站建设与管理就业方向
  • 烫画图案设计网站企业网站上线
  • 深圳手机模板建站怎么做会员自动售卡网站
  • 做网站需要懂什么接广告赚钱的平台
  • 药品和医疗器械网站icp备案前置审批流程wordpress wp rss
  • 做淘客网站要什么样服务器成都建设诚信网站
  • 自学网站开发需要多久建一个c2c网站要多少钱