不落辰

知不可乎骤得,托遗响于悲风

0%

操作系统-并发06-bug-数据竞争

  • 并发bug 之 数据竞争 Data Race

    • 不同的线程同时访问同一段内存,且至少有一个是写
    • 为处理Data Race,我们需要一个互斥的协议,而peterson这种纯软的算法,太难了。故 我们应当使用(互斥)锁 消灭datarace
  • ThreadSanitizer原理

    • 不同线程对一块共享内存操作 且至少有一个是写。对这些动作的执行顺序进行排序,若检验出无法排序的(即排序结果不唯一),则error
  • 学习自jyy

Data Race

概述

  • 起因:不上锁不就没有死锁了吗?

  • 概念:不同的线程同时访问同一段内存,且至少有一个是写

  • 两个内存访问在 “赛跑”,“跑赢” 的操作先执行。

    • 因此我们不知道执行后的状态到底是什么,是否是我们想要的状态。
  • 如peterson-barrier.c: 内存访问都在赛跑
    • 对于peterson算法,我们回想,如何留下最少的 fence,依然保证算法正确?很难的。

解决

  • Peterson 算法告诉大家:
    • 你们写不对无锁的并发程序
    • 所以事情反而简单了
  • 解决:
    • 用互斥锁保护好共享数据,消灭一切数据竞争
  • 以下代码概括了你们遇到数据竞争的大部分情况
    • bug 几乎都是这两种情况的变种
      1
      2
      3
      4
      5
      6
      // Case #1: 上错了锁
      void thread1() { spin_lock(&lk1); sum++; spin_unlock(&lk1); }
      void thread2() { spin_lock(&lk2); sum++; spin_unlock(&lk2); }
      // Case #2: 忘记上锁
      void thread1() { spin_lock(&lk1); sum++; spin_unlock(&lk1); }
      void thread2() { sum++; }

其他类型的并发bug

  • 回顾我们实现并发控制的工具

    • 互斥锁 (lock/unlock) - 原子性
    • 条件变量 (wait/signal) - 同步
  • 忘记上锁——原子性违反 (Atomicity Violation, AV)

  • 忘记同步——顺序违反 (Order Violation, OV)

  • Empirical study: 在 105 个并发 bug 中 (non-deadlock/deadlock)

    • MySQL (14/9), Apache (13/4), Mozilla (41/16), OpenOffice (6/2)
    • 97% 的非死锁并发 bug 都是 AV 或 OV。

原子性违反(AV)

  • ABA
    • 我以为一段代码没啥事呢,但被人强势插入了

顺序违反 (OV)

  • BA
    • 怎么就没按我预想的顺序来呢?
      • 例子: concurrent use after free

bug排查

Lockdep 运行时死锁检查

ThreadSanitizer: 运行时的数据竞争检查

  • 检验dataRace ; 为所有事件建立 happens-before 关系图
    • 对于发生在不同线程且至少有一个是写的 x,y检查
    • 会有不能排队的事件 检验出来