VC++中没有互斥锁的Spinlock同步.h
Spinlock sync in VC++ without mutex.h
我有点迷路了。我相信我在这里拥有的是绝对线程安全的,但我不确定它是否是。我需要一个非常快速的旋转锁机制,用于更复杂的锁的小部分,以优化线程锁定和释放(我需要制作一个更大的锁,它总是按线程被阻止的顺序释放线程-这在互斥体/EnterCriticalSection中是不会发生的)。然而,当谈到制作最小、最快的锁时,我真的不知道该怎么办。
class SpinGate
{
private:
volatile LONGLONG key = 0;
volatile LONGLONG gate = 1;
public:
void EnterGate();
void ExitGate();
};
void SpinGate::EnterGate()
{
LONGLONG myKey = InterlockedAdd64(&key, 1);
while (myKey != gate) {}
}
void SpinGate::ExitGate()
{
InterlockedAdd64(&gate, 1);
}
我认为我构建的这个东西将确保,即使1000000000个线程试图同时获得一个密钥,他们也会获得不同的密钥,因此被迫旋转,直到他们的密钥出现。但是,当谈到C++时,在没有标准库对象的情况下实现对内存的安全读写的机制在某种程度上超出了我的知识范围。
我很好奇像"interkedadd64"这样的函数是如何同时执行两个操作的,一个是增量,然后是读取,同时阻塞其他线程。无论这是否始终线程安全。
我认为我构建的这个东西将确保,即使1000000000个线程试图同时获得一个密钥,它们也会获得不同的密钥,因此被迫旋转,直到它们的密钥出现。
没有。C++volatile
关键字不提供任何线程间保证。
我很好奇像"interkedadd64"这样的函数是如何同时执行两个操作的,一个是增量,然后是读取,同时阻塞其他线程。不管这是否总是线程安全的。
它不会阻塞其他线程。在现代CPU上,它只是在原子操作的持续时间内锁定缓存线,这样在读取和写入之间就没有其他内核可以访问该内存位置。
免责声明。我真的不鼓励开发人员编写自己的锁机制。大多数自定义锁实现都无法通过以下任何测试:
-
很少有自制的实现试图保证有序的公平性。(一个以较高优先级运行的线程可能会使另一个线程无法获得锁)。
-
很难做到正确。更难维护。当你有虫子的时候,你会把头撞在墙上的。
-
当一个简单的Windows CriticalSection锁就足够了时,实际上并不需要。
但既然OP问了,我就试试看。你可能喜欢它。其他人可能会对它吹毛求疵。
在我的实现中,我添加了一些额外的工作,以允许同一线程递归地获取锁。我想你可以把这个拿出来,然后没事。
class SpinGate
{
private:
DWORD _dwOwnerThread;
LONG _ownerCount;
public:
SpinGate()
{
_dwOwnerThread = 0;
_ownerCount = 0;
}
void EnterGate()
{
LONG currentThread = (LONG)GetCurrentThreadId();
LONG result = 0;
bool owned = false;
// if we own the lock, just increment it
result = InterlockedCompareExchange(&_dwOwnerThread, currentThread, currentThread);
if (result == currentThread)
{
// we own the lock, so increment and exit
_ownerCount++;
owned = true;
}
// otherwise, spin
while (owned == false)
{
result = InterlockedCompareExchange(&_dwOwnerThread, currentThread, 0);
if (result == 0)
{
_ownerCount = 1;
owned = true;
}
else
{
while (_dwOwnerThread != 0)
{
__asm
{
pause;
}
}
}
}
return;
}
void ExitGate()
{
LONG currentThread = (LONG)GetCurrentThreadId();
LONG result = 0;
// if we don't own the lock, this is a developer error!
result = InterlockedCompareExchange(&_dwOwnerThread, currentThread, currentThread);
if (result != currentThread)
{
// ERROR - Caller attempted to exit a gate he didn't own
// ASSERT(FALSE);
return;
}
_ownerCount--;
if (_ownerCount == 0)
{
// give up the lock
result = InterlockedCompareExchange(&_dwOwnerThread, 0, currentThread);
}
return;
}
};
- 松弛原子与无同步情况下的记忆连贯性
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 在C++中同步线程
- 与 stdio 同步是否使程序 I/O 非交互式?
- 如何在qt中同步应用程序和显示器的刷新率?
- Windows 进程间同步类似事件?
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- 将 10 个线程与原子布尔值同步
- ofstream::close() 是否在 Linux 上调用同步?
- 与Visual Studios(c ++)同步时如何组织github存储库?
- 原子获取是否与互斥锁释放同步?
- Boost (Beast) websocket:同步写入挂起
- Postgres vs MySQL:命令不同步;.
- 线程过程中的线程同步问题
- 同步读取多个 TCP 响应
- 同步两个具有不同帧速率的传感器
- 如何定期同步线程?
- 同步对多个向量进行排序
- 同步类中的公共变量
- VC++中没有互斥锁的Spinlock同步.h