为什么当另一个线程释放信号量时无法立即获取信号量?

问题描述 投票:0回答:1

这是代码:

#include <iostream>
#include <semaphore>
#include <thread>
#include <chrono>

std::binary_semaphore sema{ 1 };

int main()
{
    std::thread th([]
        {
            while (true)
            {
                sema.acquire();
                std::cout << "still hold\n";
                std::this_thread::sleep_for(std::chrono::milliseconds(50));
                sema.release();
            }
        });

    std::this_thread::sleep_for(std::chrono::seconds(1));

    std::cout << "try get\n";
    sema.acquire();
    std::cout << "semaphore get\n";

    std::this_thread::sleep_for(std::chrono::seconds(10000));
}

主线程应该能够立即获取到这个信号量,因为std::thread快速释放并重新获取信号量,此时主线程应该能够获取到这个信号量。

但实际上主线程并不是立即得到这个信号量,而是在std::thread循环了很多次之后,可能只有几次,也可能是几十次。

我使用msvc(c++20)。

那么为什么主线程不能立即获取到呢?

c++ multithreading c++20 semaphore binary-semaphore
1个回答
0
投票

C++ 线程和并发模型不保证等待锁的线程的“公平性”或“饥饿自由”。根据实现的不同,释放信号量会将主线程标记为“准备运行”,但不一定会将信号量交给主线程,也不一定会立即开始执行。由于

th
线程所做的下一件事就是重新获取信号量,因此主线程没有时间来获取它。可以以保证公平的方式实现信号量,但它更复杂并且会降低性能,特别是在多核系统上。

如果你想保证这样的公平性,条件变量是更好的方法,因为它们涉及线程显式让步给每个等待获取特定互斥锁的线程。

© www.soinside.com 2019 - 2024. All rights reserved.