1. mutex - 通常用来解决data race,但是对于那种order级别的race condition不好解决。线程具有唯一性,即lock他才有资格unlock他
2. semaphore - 既可以解决data race又可以解决race condition,但是如果仅仅只有data race,不建议使用信号量。和mutex不同,没有唯一性,各个线程都可以对其进行release
3. condition variable - 主要用来解决race conditions(ordering),需要和mutex配合使用。
PS:
这里也有几个关于多线程出现问题的术语:
1. Deadlock(死锁) - A wait B, B wait A
2. Starvation(挨饿) - 某个线程一直在等某个信号量,但是每次信号量唤醒都给了更高优先级的其他线程,导致这个线程一直在等
3. Spurious wake-ups - 来源于条件变量condition variables的实现,因此在使用条件变量的时候,都会多一步去check此时的唤醒是否真的来自于condition variable
4. Priority inversion(优先级反转) - 较高优先级的线程在wait比较低优先级的resource,这样就会让用户困惑。比如对于声卡来说播放音乐很重要(高优先级),但如果你让他去等待一个微不足道的UI显示(低优先级),这就会造成这个问题
这几种操作其实都是类似blocking机制,他会让你的你的线程进入到睡眠。然而随着多线程的发展,现在出现了一种实现方式可以让你的线程不进行sleep从而加快你程序的整个处理速度。这个一般通过atomic primitives & lock-free data structures来实现。