使用x86程序集的信号量实现



我对信号量的实现方案很感兴趣,我了解到在x86中,我们可以使用"锁前缀"来实现原子操作,我想用它来实现互斥,我知道C++11现在有标准的互斥,但我想实现我自己的互斥。这是我的代码:

#include <iostream>
#include <thread>
#include <vector>
struct Semaphore
{
private:
    int s;
public:
    Semaphore( int s ) : s(s){}
    void wait()
    {
        int *p = &s;
        _asm
        {
            mov eax, p
            lock dec DWORD PTR [eax]
    begin : mov ebx, DWORD PTR [eax]
            cmp ebx, 0
            jl begin
        };
    }
    void signal()
    {
        int *p = &s;
        _asm
        {
            mov eax, p
            lock inc DWORD PTR [eax]
        };
    }
} s(1);
void print()
{
    s.wait();
    std::cout << "Print Thread " << std::this_thread::get_id() << std::endl;
    s.signal();
}
int main( int argc, char* argv )
{
    std::vector< std::thread > vec;
    int n = 3;
    for( int i = 0; i < n; ++i ) vec.push_back( std::thread( print ) );
    for( int i = 0; i < n; ++i ) vec[i].join();
    return 0;
}

问题是,当有两个线程时,代码运行良好,而在有三个线程的情况下,程序似乎陷入了死锁状态,有人能解释为什么吗?或者给我一些关于如何在x86机器上实现is的建议吗?

您的wait实际上是一个spinlock——当锁处于争用状态时,它将(尝试)使用100%的CPU,直到其他线程释放信号量。不幸的是,由于它使用了100%的CPU,这会阻止其他线程获得CPU时间,因此您会得到接近死锁的东西。

据猜测,您可能正在双核CPU上运行。在这种情况下,另一个线程可以全速运行,即使自旋锁处于紧张的循环中,也会浪费CPU时间。当获得的线程数超过可用的CPU核心数时,事情就会陷入停顿。

如果您有充分的理由相信信号量会很快被清除(在这种情况下,您希望避免任务切换的开销),那么旋转锁可能会很有用。然而,在一个典型的情况下,你想限制花在"旋转"上的时间,所以你的循环看起来像:

        mov ecx, 100
begin : mov ebx, DWORD PTR [eax]
        test ebx, ebx
        loopnz begin

然后,在它脱离循环后,检查信号量是否已清除,或者是否达到了极限(在本例中为100次迭代)。如果达到了限制,则调用调度程序让其他线程运行(并在该线程再次运行时重试等待)。

您创建的代码不是信号量的正确实现。信号量应该将等待任务放入信号量的等待队列;在那之后,它的代码不运行,直到信号量再次被发信号;当信号量被发出信号时,一个等待的线程被唤醒。一半的信号量代码在内核中,关于如何访问它的详细信息在线程库实现中。因此,为了正确地实现信号量,在C++中,您需要做一些更复杂的事情。或者你可以编写自己的操作系统。

此外,您没有说明您使用的编译器,但您的编译器可能过于激进地优化了asm子句。

这里有多个问题。这里有两个。

  1. 您的wait()例程无条件递减计数器。如果你有两个服务员,那么你的计数将是-2,在任何服务员停止等待之前,你需要两个信号。

  2. 编写的信号量代码完全依赖于调度程序。因此,根据调度器以及等待和信号器的优先级,等待任务(繁忙循环)完全有可能永远不会屈服于另一个执行上下文。

希望这能有所帮助。

是的,我承认如果没有操作系统或机器的帮助,我无法实现我自己的版本,所以我尝试使用C++11标准来实现它,我发现斯坦福大学的一门课程提供了一个解决方案,我想与任何需要它的人分享它,下面是链接:http://www.stanford.edu/class/cs110/lectures/18-threading-and-semaphores.html#(3)

最新更新