自旋锁未消耗 100% cpu

spin locks not consuming 100% cpu

#include "boost/smart_ptr/detail/spinlock.hpp"
boost::detail::spinlock lock;
main(){
    std::lock_guard<boost::detail::spinlock> guard(lock);
    while(true)
        {
                i=i+100;
        }
}

机器详细信息:

CPU(s): 2

在线CPU(s)个列表:0,1

每个核心线程数:1

每个插槽的内核数:2

插座:1

以上代码中,当i 运行 :

First instance => 它占用了 cpu 的 100%(根据 top 命令)

Second instance => 花费了 97-98%,这两个实例的总和显示大约 195%-197%

Third instance => 通过调整 cpu 前两个实例的消耗,它花费了 ~47-50% 并且这三个实例的总和显示接近 200% 。

我的假设是,一旦自旋锁获得 cpu,它就不会被 cpu 抢占(它不会被 cpu 通过调度一些这次其他线程将线程(自旋锁定)保持在调度队列中),因此我期望第三个实例失败。 但它 运行 显示前两个进程线程已被抢占。

我哪里弄错了?

我想你误解了什么是自旋锁。它并不比这复杂多少:

class SpinLock {
public:
    void lock() {
        while (is_locked) { /*do nothing*/ }
        // ...MAGIC HAPPENS HERE...
        is_locked = true;
    }

    void unlock() {
        is_locked = false;
        // ...SUBTLE magic happens here...
    }

private:
    bool is_locked = false;
};

MAGIC 是使用特殊机器指令* 的代码,以确保如果 while 循环中同时有多个线程 "spinning",只有 其中一个 将看到 is_locked == false 并在其他线程调用 unlock() 函数时退出循环。

My assumption was that, once the spin lock acquires the cpu...

自旋锁中没有任何东西可以 "acquire" CPU。这只是获取的代码 运行 by a CPU,与您程序中的任何其他代码没有区别。经营的 系统 (OS) 决定哪个线程 运行 在哪个 CPU 上以及什么时候,什么都没有 自旋锁确实会影响它。

...it doesn't get preempted by CPU.

A CPU 不会抢占任何东西。 CPU 只是执行代码。当 CPU 发生时 待运行ningOS代码,OS可以选择抢占当前线程。旋转 锁对哪个线程被抢占、何时被抢占或为什么被抢占没有任何影响。

"Preempt," 表示 OS 暂停一些 运行ning 线程并允许其他一些 线程转向 运行。每次可能发生 100 次左右 其次,通常,none 所涉及的线程知道它。

自旋锁对抢占没有影响的原因是,它们只是 代码。纯自旋锁不会调用 OS 或与 OS 进行通信 反正。 OS 无法区分线程是 计算 pi 的数字,或正在平衡银行账户的线程,或正在等待自旋锁的线程。


unlock()函数中的SUBTLE magic内存屏障组成 指令 用于 强制使用 C++ 内存 型号。这是一个深奥的话题—— 这个答案太深了。


* C++ Atomic operations library 让您可以低级访问那些 "special" 机器指令。