- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
编辑: 看起来,问题是我实际上并没有创建一个 lock_guard 的本地实例,而只是一个匿名的临时实例,它立即再次被销毁,如下面的评论所指出的。
Edit2:启用 clang 的线程清理器有助于在运行时查明这些类型的问题。它可以通过
启用clang++ -std=c++14 -stdlib=libc++ -fsanitize=thread *.cpp -pthread
这在某种程度上可能是一个重复的问题,但我找不到任何东西,所以如果它真的是重复的,我很抱歉。无论如何,这应该是一个初学者问题。
我正在玩一个简单的“Counter”类,比如在文件中内联
计数器.hpp:
#ifndef CLASS_COUNTER_HPP_
#define CLASS_COUNTER_HPP_
#include <mutex>
#include <string>
#include <exception>
class Counter
{
public:
explicit Counter(std::size_t v = 0) : value_{v} {}
std::size_t value() const noexcept { return value_; }
// void increment() { ++value_; } // not an atomic operation : ++value_ equals value_ = value_ + 1
// --> 3 operations: read, add, assign
void increment() noexcept
{
mutex_.lock();
++value_;
mutex_.unlock();
}
// void decrement() noexcept
// {
// mutex_.lock();
// --value_; // possible underflow
// mutex_.unlock();
// }
void decrement()
{
std::lock_guard<std::mutex>{mutex_};
if (value_ == 0)
{
std::string message{"New Value ("+std::to_string(value_-1)+") too low, must be at least 0"};
throw std::logic_error{message};
}
--value_;
}
private:
std::size_t value_;
std::mutex mutex_;
};
#endif
在 main.cpp 中,一个 Counter 实例应该被递增和递减同时:
主要.cpp:
#include <iostream>
#include <iomanip>
#include <array>
#include <thread>
#include <exception>
#include "Counter.hpp"
int
main ()
{
Counter counter{};
std::array<std::thread,4> threads;
auto operation = [&counter]()
{
for (std::size_t i = 0; i < 125; ++i)
counter.increment();
};
// std::for_each(begin(threads),end(threads),[&operation](auto& val) { val = std::thread{operation}; });
std::cout << "Incrementing Counter (" << std::setw(3) << counter.value() << ") concurrently...";
for (auto& t : threads)
{
t = std::thread{operation};
}
for (auto& t : threads)
t.join();
std::cout << " new value == " << counter.value() << '\n';
auto second_operation = [&counter]()
{
for (std::size_t i = 0; i < 125; ++i)
{
try
{
counter.decrement();
}
catch(const std::exception& e)
{
std::cerr << "\n***Exception while trying to decrement : " << e.what() << "***\n";
}
}
};
std::cout << "Decrementing Counter (" << std::setw(3) << counter.value() << ") concurrently...";
for (auto& t : threads)
t = std::thread{second_operation};
for (auto& t : threads)
t.join();
std::cout << " new value == " << counter.value() << '\n';
return 0;
异常处理似乎按预期工作,并且我理解它的方式 std::lock_guard 应该保证一旦 lock_guard 超出范围就解锁互斥量。
然而,它似乎比这更复杂。虽然递增正确地导致最终值为“500”,但递减(本应为“0”)却没有结果。结果将介于“0”和“16”之间。
如果时间发生变化,例如通过使用 valgrind,它似乎每次都能正常工作。
我能够查明问题出在 std::lock_guard 的使用上。如果我这样定义 decrement() 函数:
void decrement() noexcept
{
mutex_.lock();
--value_; // possible underflow
mutex_.unlock();
}
一切正常(只要没有下溢)。但是一旦我做了一个简单的改变:
void decrement() noexcept
{
std::lock_guard<std::mutex>{mutex_};
--value_; // possible underflow
}
行为就像我上面描述的那样。我想我并没有真正理解 std::lock_guard 的行为和用例。如果您能指出正确的方向,我将不胜感激!
程序通过 clang++ -std=c++14 -stdlib=libc++ *.cpp -pthread
编译。
最佳答案
std::lock_guard<std::mutex>{mutex_};
不创建本地。它创建一个临时文件,在语句结束时销毁。这意味着您的值(value)不受锁的保护。锁守卫必须是本地的:
void decrement() noexcept
{
std::lock_guard<std::mutex> guard {mutex_};
--value_; // possible underflow
}
关于c++ - std::lock_guard 导致未定义的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34612707/
我有一个函数 foo在多个线程中运行(std::thread t([&]() { foo(a); }): void foo(int a) { if (x && y != a) {
我有包含在 shared_ptr 中的资源“resource”,我想从其他线程访问它。当我这样做时: // foo.h class Foo{ public: std::shared_ptr G
这个问题在这里已经有了答案: Is a copy-on-return operation executed prior or after lock_guard destructor? [duplica
我写了 3 个互斥类 TMutex、TCondition 和 TSpinLock 都有一个 void lock() 和一个 void unlock() 成员。现在我想对它们使用 std::lock_g
一个线程有如下的控制流程: mutex.lock() if (condition) { // do synced things mutex.unlock(); // do pa
我有一个数组,其中每个条目都是一个链表。为了避免在访问链接列表时出现同步问题,我为每个条目添加了一个互斥量。 我的问题是,我能否将循环的每次迭代中对 lock 和 unlock 的以下调用转换为一个
我刚刚了解到 std::lock_guard 我想知道为什么它是一个模板。 到现在我只看到std::lock_guard与 std::mutex在尖括号内。 最佳答案 使用 std::lock_gua
我刚刚了解到 std::lock_guard 我想知道为什么它是一个模板。 到现在我只看到std::lock_guard与 std::mutex在尖括号内。 最佳答案 使用 std::lock_gua
如果我在 lock_guard 下有一些代码,例如: std::thread t([&]() { std::lock_guard lock(m); // some simple ope
我正在使用一些多线程代码(使用并发数据结构),其中一部分需要我锁定一组互斥锁。对于我的实现,我使用了一个 lock_guards vector ,因为我不一定知道我需要锁定多少个互斥锁,而且我可能会遇
我认为这是关于左值实例化排序的更普遍的问题。 简而言之,这安全吗?: void func1() { std::lock_guard lock( mutex ); //do some s
https://en.cppreference.com/w/cpp/thread/lock_guard (constructor) constructs a lock_guard, optionall
[无需点击链接即可理解问题]。 我在this answer中结合了单例模式的实现, 连同 this other answer 的同步文件写入. 然后我想看看SynchronizedFile的接口(in
我试图在以下代码中锁定我的互斥量列表,以便一次只有一个线程可以搜索、解锁、锁定或修改它。 #include #include #include #include #include #incl
编辑: 看起来,问题是我实际上并没有创建一个 lock_guard 的本地实例,而只是一个匿名的临时实例,它立即再次被销毁,如下面的评论所指出的。 Edit2:启用 clang 的线程清理器有助于在运
我有简单的代码:第一个线程将 std::strings 推送到 std::list,第二个线程弹出 std::strings 从这个 std::list。所有 std::list 的操作都受到 std
我目前正在研究 Google 的 Filament 作业系统。你可以找到源代码 here .让我感到困惑的部分是这个 requestExit() 方法: void JobSystem::request
这个问题在这里已经有了答案: C++ return value created before or after auto var destruction? (2 个答案) in C++ which
在下面的代码中,bad 方法编译失败,但是 good 方法没有。为什么提供对 this 的显式引用在这里有所不同? #include class Foo { private: std::mut
我有一个函数,语句 foo 应该在 lock_guard 下执行,但只有当一个指向 mutex 对象的指针被提供给函数作为参数。否则 foo 不必由 lock_guard 保护。 我不能在 if 中使
我是一名优秀的程序员,十分优秀!