#include <windows.h>
#include <iostream>
DWORD tID;
volatile double fps;
DWORD WINAPI ThreadFunc(LPVOID param)
{
while (1)
{
//Need lock-free solution here
std::cout << GetCurrentThreadId() << " Thread: " << fps << std::endl;
Sleep(1);
}
return 1;
}
void mainFunc(const double& pGps)
{
//Perormance critical function - should be lightwieght as possible as it can
fps = pGps; // need lock-free efficient solution
}
int main()
{
double gps, pGps =0.0;
auto fb1 = CreateThread(NULL, NULL, &ThreadFunc, &gps,0,&tID);
while (1)
{
pGps = pGps + 1;
mainFunc(pGps);
Sleep(1);
}
system("Pause");
return 0;
}
我正在使用Visual C ++编译器。 这里 fps 双变量在主线程和 fb1 线程之间共享,我需要在良好同步的机制中建立并发写和读访问。这里只需要考虑两个线程。主线程 - 制作人 (作家),fb1线程将是 消费者 (读者)。
这就是问题, mainFunc 应该更轻量级,更高效(指令数量更少)。我尝试了使用std::atomic<double> fps
,Win32 Interlocked操作的不同方法,但我无法#39;达到预期的性能。
首先,我尝试使用 Slim R / W 锁定,但解决方案应该是无锁机制,即使SRW锁定没有提供所需解决方案的性能。
请通过引入无锁数据结构检查以下修改后的代码
DWORD tID,tID1;
volatile double fps;
LK_Free_DataStructre datStruct;
DWORD WINAPI ThreadFunc(LPVOID param)
{
while (1)
{
size_t n = datStruct.size();
for (auto i = 0; i < n; ++i)
{
std::cout << GetCurrentThreadId() << " Thread: " << datStruct.get(i) << std::endl;
}
Sleep(1);
}
return 1;
}
void mainFunc(double& pGps)
{
datStruct.insert(pGps);
}
int main()
{
double gps, pGps =0.0;
auto fb1 = CreateThread(NULL, NULL, &ThreadFunc, &gps,0,&tID);
while (1)
{
pGps = pGps + 1;
mainFunc(pGps);
Sleep(1);
}
system("Pause");
return 0;
}
假设我们必须定义 无锁 和 轻量级 数据结构 - 这是 LK_Free_DataStructre 即可。 那么构建数据结构中最合适的 Win32 或 C / C ++ 是什么,可以取代 LK_Free_DataStructre ?
推荐std::atomic<double>
吗?
答案 0 :(得分:1)
在这种情况下,最简单,最快速的答案是std::atomic<double>
- 它基本上是为此而设计的。你只需要避免std :: memory_order_seq_cst强加的内存栅栏(默认的内存顺序)。像下面这样的东西根本没有同步,只是原子性(一次性移动一个双倍的记忆),所以几乎和指定一个普通的双变量一样快,同时仍然是安全的。
#include <atomic>
std::atomic<double> fps;
void setFps(double val) {
fps.store(val, std::memory_order_relaxed);
}
double getFps() {
return fps.load(std::memory_order_relaxed);
}
如果你使用无锁数据结构(例如队列),那么
所以我会避免这种情况。
微软的联锁操作与std :: atomic基本相同,只是非标准且难以使用(IMO),所以我也会避免这种情况。
答案 1 :(得分:0)
这里只需要考虑两个线程。主线程 - 生产者(编写者),fb1线程将是消费者(Reader)。
听起来你需要的是单生产者/单一消费者队列。
您可能希望查看Boost Single-Producer/Single-Consumer Queue用法示例。
单生产者/单一消费者队列的好处在于它可以以无等待的方式实现(除了无锁)。也就是说,push
和pop
操作在固定数量的指令中完成,不会涉及繁忙的等待。