多线程编程初步

前言

非常不喜欢这种“X一峰”式的文章。但是为了伟大的教育事业,还是要写一点的。

线程安全的定义

无论操作系统如何调度线程,无论这些线程的执行顺序如何交织。一个函数(或类)在多个线程同时访问时能表现出正确的行为,而无需调用端代码进行额外的同步或协调操作。

划重点:

  • 无论如何调度
  • 无需额外的同步或协调操作
  • 总能表现出正确的行为

竞态条件(race condition)

竞态条件描述的是一个系统或者进程的输出依赖于不受控制的事件出现顺序或者出现时机。例如两个进程“同时读写”一块内存,其结果一定是不受控制的。

“同时读写”的定义包括:

  • 一读一写
  • 一写多读
  • 多写一读
  • 多写多读
  • 多写

也就是说,只要包含“并发”和“写操作”两个特性,就会出现竞态条件。而“多读”一般来说是安全的。

同时也要注意,这里的读与写是物理意义上的读写,而不是逻辑意义上的。有一些函数看起来只有读操作,但其内部仍然包括了对数据的修改,这里需要注意甄别。

Mutex - 互斥锁 …

more ...

实现一个无锁消息队列

目标

实现一个多读多写的无锁消息队列。

cmpxchg - 比较并替换

比较并替换(compare-and-swap, CAS)是一个用于多线程同步的原子操作。

其工作流程是:

def cmpxchg(val, oldval, newval):
    if val == oldval:
        val = newval
        return True
    return False

也就是说,只有当val等于oldval时,我们才会将val的值替换成newval。在多线程的场景下,cmpxchg用来保证多线程写的原子性。

例如,线程1和线程2都要写入val变量,但是我们需要保证只有一个线程能写成功。使用cmpxchg,能保证只有一个线程能成功的将val变量替换成新值,写失败的线程会得到False的返回值。

ACCESS_ONCE - 消除优化歧义

#define …
more ...