多线程编程问题

1. int变量操作的原子性

x86汇编中,对任何内存地址中的1byte的读永远是原子的。可以总结为:在对齐的情况下,小于处理器位数的数据读取是原子的。但在C++中,使用强制转换后的内容不再保证对齐,于是就没有了原子性。基于这些原因,在程序中应该直接atomic相关的函数来保证原子性。

2. volatile在多线程中应该怎么用

上一条中说明了不能用一个变量来保证原子性,即使加上volatile也没用。在多线程中,volatile应该用于在加锁的前提下,防止指令不会因编译器的优化而省略,且要求每次直接读值。

3. 什么是指令乱序

处理器乱序 是指在执行指令时,如果后一第指令不依赖前一条的执行结果,则后一条指令有可能会在前一条指令返回前执行。处理器乱序不会对上层的运行结果产生影响。

编译器乱序 是为了优化处理器乱序,受到处理器预取单元的能力限制,处理器每次只能分析一小块指令,编译器能够对很大一个范围的代码进行分析,并将其尽量靠近排列让处理器更容易预取和并发执行。

通常简单地使用volatile关键字就可以解决编译器的乱序问题(并不能保证编译器不做其他任何优化),但是这些指令到了处理器执行的时候,仍然可能被乱序。对于处理器乱序执行的避免就需要用到一组 内存屏障 函数(barrier)了。

对于切实是需要保障访存顺序的代码,就算当前使用的编译器能够编译出有序的目标码来,我们也还是必须通过设置内存屏障的方式来保证有序,否则都是不严谨,有隐患的。

4. 自旋锁

自旋锁与互斥锁类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环查询锁的保持者是否已经释放了锁。因为自旋锁不会引起调用者睡眠,所以自旋锁的效率高于互斥锁,但也应该考虑其一直占用CPU带的影响,适用于锁持有时间短,不希望在调度上花太多成本。在《APUE》11.6.7有详细介绍。

你可能感兴趣的:(多线程,编程)