我在我的一个项目中有一个特定的要求,即保持某些操作的“计数”,并最终定期“读取”+“重置”这些计数器(例如24小时)。
操作将是:
我感兴趣的平台是Windows,但是如果这个可以跨平台就更好了。我正在使用 Visual Studio,目标 Windows 架构仅是 x64。
我不确定结果是否“ok”以及我的实施是否正确。坦率地说,我从未使用过太多 std 包装器,而且我的 C++ 知识非常有限。
结果是:
12272 Current: 2
12272 After: 0
12272 Current: 18
12272 After: 0
12272 Current: 20
12272 After: 0
12272 Current: 20
12272 After: 0
12272 Current: 20
12272 After: 0
Run Code Online (Sandbox Code Playgroud)
下面是一个完全复制/粘贴的可重现示例:
12272 Current: 2
12272 After: 0
12272 Current: 18
12272 After: 0
12272 Current: 20
12272 After: 0
12272 Current: 20
12272 After: 0
12272 Current: 20
12272 After: 0
Run Code Online (Sandbox Code Playgroud)
我应该提到,在我的现实项目中,没有使用 std::thread 包装器,并且线程是使用 CreateThread 等 WinApi 函数创建的。以上只是模拟/测试代码。
请向我指出上面的代码有什么问题,可以改进什么,以及我的方向是否正确。
谢谢你!
Haj*_*off 11
你为什么要写一ThreadSafeCounter堂课?
std::atomic<size_t> 是一个线程安全计数器。这就是 std::atomic 的全部意义。所以你应该改用它。不需要再上一堂课。大多数原子都有operator++/operator--专业化,所以你的主循环可以很容易地重写如下:
static std::atomic_int ThreadCounter1(0);
auto Thread1 = []() {
while (true)
{
auto test = ++ThreadCounter1; // or ThreadCounter1++, whatever you need
std::cout << std::this_thread::get_id() << " Threads.IncCounter1() -> " << test << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
}
};
auto Thread2 = []() {
while (true)
{
auto test = --ThreadCounter1;
std::cout << std::this_thread::get_id() << " Threads.DecCounter1() -> " << test << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
}
};
auto Thread3 = []() {
while (true)
{
/* Note: You could simply "ThreadCounter1 = 0" assign it here.
But exchange not only assigns a new value, it returns the previous value.
*/
auto ValueAtReset=ThreadCounter1.exchange(0);
std::cout << std::this_thread::get_id() << " Threads.ClearCounter1() called at value" << ValueAtReset << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
}
};
Run Code Online (Sandbox Code Playgroud)
我忘了提及您的 DecCounter 操作的问题。您正在使用atomic_uint,它无法处理负数。但不能保证您的 Thread2 不会在 Thread1 之前运行(也称为递减计数器)。这意味着你的柜台将会换行。
所以你可以/应该使用std::atomic<int>。这将为您提供正确的数量(calls_Thread1 - Calls_Thread2)。如果 Thead2 比 Thread1 更频繁地递减该值,则该数字将变为负数。