gpt4 book ai didi

c++ - 使用 x86 汇编的信号量实现

转载 作者:太空狗 更新时间:2023-10-29 23:51:53 26 4
gpt4 key购买 nike

我对信号量实现方案很感兴趣,我了解到在 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;
}

问题是,当有两个线程时,代码运行良好,而如果有 3 个线程,程序似乎陷入死锁状态,谁能解释为什么或给我一些关于如何实现的建议 is on x86 机器?

最佳答案

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

据推测,您可能在双核 CPU 上运行。在这种情况下,另一个线程可以全速运行,即使自旋锁处于紧密循环中,浪费 CPU 时间。当您获得的线程多于可用的 CPU 内核时,事情就会停止。

如果您有充分的理由相信信号量会很快清除(在这种情况下您希望避免任务切换的开销),自旋锁会很有用。然而,在典型情况下,您想限制“旋转”所花费的时间,因此您的循环看起来像:

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

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

关于c++ - 使用 x86 汇编的信号量实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18235599/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com