Dekker algorithm是一种著名的并发编程的算法,Dekker算法的核心部分是一组对称的代码来访问一组共享变量,使得两个线程不可能同时进入临界区(只要cpu内存模型是遵循顺序一致性的),从而达到线程同步的目的。以下是该算法的一种实现:

static volatile int flag1 = ;
static volatile int flag2 = ;
static volatile int turn = ;
static volatile int gSharedCounter = ; void dekker1( ) {
flag1 = ;
turn = ;
while((flag2 == ) && (turn == )) ;
// Critical section
gSharedCounter++;
// Let the other task run
flag1 = ;
} void dekker2(void) {
flag2 = ;
turn = ;
while((flag1 == ) && (turn == )) ;
// critical section
gSharedCounter++;
// leave critical section
flag2 = ;
}

该实现的关键在于while((flag2 == 1) && (turn == 2))与while((flag1 == 1) && (turn == 1))永远不可能同时成立,从而可以互斥的访问临界区,并且由于条件不可能同时成立,也不会导致死锁。以下面的例子进行测试:

int gLoopCount;
void *task1(void *arg) {
int i;
printf("Starting task1n");
for(i=gLoopCount;i>;i--) {
dekker1();
}
}
void *task2(void *arg) {
int i;
printf("Starting task2n");
for(i=gLoopCount;i>;i--) {
dekker2();
}
}

在单核处理器下,以多线程的方式执行这段代码,无论运行多少次,程序也不会出错。因为单核CPU的内存模型是遵循顺序一致性(Sequential Consistency)的,Sequential Consistency模型(后面简称SC),简单说它其实就是我们印象中多线程程序应该有的执行顺序。但是,SC最大的问题是性能太低了,因为CPU/编译器完全没有必要严格按代码规定的顺序(program order)来执行每一条指令。学过体系结构的同学应该知道不管是编译器也好CPU也好,他们最擅长做的事情就是帮你做乱序优化。在串行时代这些乱序优化对程序员来说都是透明的,封装好了的,你不用关心它们到底给你乱序成啥样了,因为它们会保证优化后的程序的运行结果跟你写程序时预期的结果是一模一样的。但是进入多核时代之后,CPU和编译器还会继续做那些串行时代的优化,更重要的是这些优化还会打破你多线程程序的SC模型语义,从而使得多线程程序的实际运行结果与我们所期待的运行结果不一致!
拿X86来说,它的多核内存模型没有严格执行SC,即属于weak ordering(或者叫relax ordering?)。它唯一允许的乱序优化是可以把对不同地址的load操作提到store之前去(即把store x->load y乱序优化成load y -> store x)。而store x -> store y、load x -> load y,以及load y -> store x不允许交换执行顺序。
因此,对于弱内存一致性的机器来说,该算法有可能会失效,因为对于按什么顺序来更新flag1和flag2是没有限制的,特别是不能保证在dekker1中对flag2的读操作发生在dekker2对flag1和turn的写操作之后。

参考:剖析为什么在多核多线程程序中要慎用volatile关键字?

Dekker算法在多核处理器下的失效的更多相关文章

  1. [转帖]AMD、英特尔为何争相走向胶水多核处理器?真相在此

    AMD.英特尔为何争相走向胶水多核处理器?真相在此 胶水多核到底好不好?这个事不是简单一句话能说明的,今天的超能课堂里我们就来聊聊MCM胶水多核技术的过去及未来. 作者:孟宪瑞来源:超能网|2018- ...

  2. Peterson算法与Dekker算法解析

    进来Bear正在学习巩固并行的基础知识,所以写下这篇基础的有关并行算法的文章. 在讲述两个算法之前,需要明确一些概念性的问题, Race Condition(竞争条件),Situations  lik ...

  3. python GIL 全局锁,多核cpu下的多线程性能究竟如何?

    python GIL 全局锁,多核cpu下的多线程性能究竟如何?GIL全称Global Interpreter Lock GIL是什么? 首先需要明确的一点是GIL并不是Python的特性,它是在实现 ...

  4. 编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器)

    [目录] 不考虑其他进程,cpu画正弦曲线 获取总体cpu利用率 获取多核处理器单个cpu利用率 考虑其他进程,cpu画正弦曲线 下面的程序针对多核处理器,可以设置让任何一个cpu显示相应的曲线(本文 ...

  5. [py]你真的了解多核处理器吗? 了解多线程

    越来越多的人搞爬虫,设计到多线程爬取, 还有一些机器学习的一些模块也需要这玩意, 感觉自己不会逼格不高. 抽时间赶紧玩一玩这东西, 希望提高对软件的认知和归属感,不要太傻. cpu内部架构参考 你知道 ...

  6. 让cpu占用率曲线听你指挥(多核处理器)

    编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器) [版权声明]转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3242910.html  [目录] 不考 ...

  7. Linux 的 Spinlock 在 MIPS 多核处理器中的设计与实现

    引言 随着科技的发展,尤其是在嵌入式领域,高性能.低功耗的处理器成为众多厂商追逐的目标,但是由于技术和工艺的瓶颈,试图在单核处理器上达到这样的目标变得越发困难,于是人们提出了多核处理器的概念.多核处理 ...

  8. 【DSP开发】硬件信号量在多核处理器核间通信中的应用

    硬件信号量在多核处理器核间通信中的应用 刘德保1,汪安民1,韩道文2 1.同方电子科技有限公司研究所,九江 332009:2.解放军电子工程学院 摘要: 在多核处理器的软件设计中,核间通信机制是关键所 ...

  9. linux多核cpu下的负载查看

    linux下使用top命令或uptime命令 单核cpu下,负载超过0.7即意味着瓶颈,多核cpu下按核数*0.7计算负载 如2核,1.4可能即意味着负载较吃力了 查看核数 grep 'model n ...

随机推荐

  1. MQTT的学习研究(七)基于HTTP POST MQTT 发布消息服务端使用

    参阅官方文档 http://publib.boulder.ibm.com/infocenter/wmqv7/v7r0/topic/com.ibm.mq.csqzau.doc/ts21220_.htm ...

  2. ReactNative For Android 框架启动核心路径剖析

    版权声明:本文由王少鸣原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/144 来源:腾云阁 https://www.qclo ...

  3. Android 判断当前是否在跑monkey测试

    /**     * Returns true if Monkey is running.     */    public static boolean isMonkeyRunning() {     ...

  4. ORA-28056 解决方法

    用pl/sql devlper 来连接oracle数据库,遇到 0RA-28056错误,解决的方法是 在 计算机-->管理 -->事件查看器里边清理应用程序日志(问题原因是应用程序的日志满 ...

  5. Egret Wing4.0.3 合并资源图片问题

    一 发布项目时,选择合并图片资源 选择合图大小 发布后,图片合并.随机了图片名字.  二  随机名的问题 当资源不变更的情况下,多次发布,每次发布后资源的图片随机名是不变的. 现在改变preload组 ...

  6. KMP的next数组性质运用

    hdu2594 Simpsons' Hidden Talents Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  7. php 常用的系统函数

    字符串函数 strlen:获取字符串长度,字节长度 substr_count 某字符串出现的次数 substr:字符串截取,获取字符串(按照字节进行截取) mb_strlenmb_substr str ...

  8. 新版jquery的ajax调用 , jquery1.5以上

    原文出处:http://api.jquery.com/jQuery.ajax/,该链接页面底部有代码展示 示例1: $.ajax({ method: "POST", url: &q ...

  9. MySQL实现根据当前ID读取上一条和下一条记录

    以下为MySQL语句演示: SELECT * FROM t_news AS n ORDER BY n.`News_ID` 当前ID为4,读取上一条记录: ,; 当前ID为4,读取下一条记录: ,; 其 ...

  10. python基础-第九篇-9.3线程池

    简单版 import queue import threading class ThreadPool(object): def __init__(self, max_num=20): self.que ...