我有两个用例.
答:我想将两个线程的访问同步到队列.
B.我想将两个线程的访问同步到队列并使用条件变量,因为其中一个线程将等待内容由另一个线程存储到队列中.
对于用例AI,请参阅代码示例std::lock_guard<>.对于用例BI,请参阅使用的代码示例std::unique_lock<>.
两者之间有什么区别,我应该在哪个用例中使用哪一个?
在 Visual Studio 2022 中以发布模式运行以下命令:
#include <chrono>
#include <mutex>
#include <shared_mutex>
#include <iostream>
std::mutex mx;
std::shared_mutex smx;
constexpr int N = 100'000'000;
int main()
{
auto t1 = std::chrono::steady_clock::now();
for (int i = 0; i != N; i++)
{
std::unique_lock<std::mutex> l{ mx };
}
auto t2 = std::chrono::steady_clock::now();
for (int i = 0; i != N; i++)
{
std::unique_lock<std::shared_mutex> l{ smx };
}
auto t3 = std::chrono::steady_clock::now();
auto d1 = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
auto d2 = std::chrono::duration_cast<std::chrono::duration<double>>(t3 - t2);
std::cout …Run Code Online (Sandbox Code Playgroud) 是get_a()功能安全的比赛条件或者我需要明确地复制str_在get_b()为了有一个线程安全的功能?
class Class {
public:
auto get_a() -> std::string {
auto&& guard = std::lock_guard{mutex_};
return str_;
}
auto get_b() -> std::string {
auto&& guard = std::lock_guard{mutex_};
auto str = str_;
return str;
}
private:
std::mutex mutex_{};
std::string str_{};
};
Run Code Online (Sandbox Code Playgroud)
注意:我知道Stack Overflow上有类似的问题,但我找不到明确回答这个问题的问题.
我见过大多数使用std::mutex互斥体是全局的例子.我想知道为什么这样做有什么具体的原因?我有自己的程序,我不这样做,只是将互斥量作为一个std::thread std::ref.拥有全局变量不是不好的做法,std::mutexes如果没有语言限制理由这样做,那么C++中全局背后的理性是什么?
采用这个简单的函数,在由std::mutex以下实现的锁定下递增整数:
#include <mutex>
std::mutex m;
void inc(int& i) {
std::unique_lock<std::mutex> lock(m);
i++;
}
Run Code Online (Sandbox Code Playgroud)
我希望这(在内联之后)以直接的方式编译,然后调用m.lock()增量.im.unlock()
检查生成的程序集的最新版本的gcc和clang,但是,我们看到一个额外的并发症.gcc首先考虑版本:
inc(int&):
mov eax, OFFSET FLAT:__gthrw___pthread_key_create(unsigned int*, void (*)(void*))
test rax, rax
je .L2
push rbx
mov rbx, rdi
mov edi, OFFSET FLAT:m
call __gthrw_pthread_mutex_lock(pthread_mutex_t*)
test eax, eax
jne .L10
add DWORD PTR [rbx], 1
mov edi, OFFSET FLAT:m
pop rbx
jmp __gthrw_pthread_mutex_unlock(pthread_mutex_t*)
.L2:
add DWORD PTR [rdi], 1
ret
.L10:
mov edi, eax …Run Code Online (Sandbox Code Playgroud) 我想知道如何才能std::atomic_ref有效地实现std::mutex非原子对象(每个对象一个),因为以下属性似乎很难实施:
相对于通过引用同一对象的任何其他atomic_ref施加的原子操作,通过atomic_ref施加到对象的原子操作是原子的。
特别是以下代码:
void set(std::vector<Big> &objs, size_t i, const Big &val) {
std::atomic_ref RefI{objs[i]};
RefI.store(val);
}
Run Code Online (Sandbox Code Playgroud)
似乎很难实现,因为std::atomic_ref每次都需要以某种方式进行选择std::mutex(除非这是由相同类型的所有对象共享的大主锁)。
我想念什么吗?还是每个对象都有责任实施std::atomic_ref,因此要么是原子的要么携带一个std::mutex?
我正在学习std::mutex,std::thread我对下面两段代码的不同行为感到惊讶:
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
std::mutex mtx;
void foo(int k)
{
std::lock_guard<std::mutex> lg{ mtx };
for (int i = 0; i < 10; ++i)
cout << "This is a test!" << i << endl;
cout << "The test " << k << " has been finished." << endl;
}
int main()
{
std::thread t1(foo, 1);
std::thread t2(foo, 2);
t1.join();
t2.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是顺序的.但如果我没有名称变量std::lock_guard<std::mutex>,则输出无序
void foo(int k)
{ …Run Code Online (Sandbox Code Playgroud) 在 static_assert 之后,gcc 和 clang 主干都通过了。
#include<mutex>
int main(){
static_assert(sizeof(std::mutex)==40);
}
Run Code Online (Sandbox Code Playgroud)
由于 x86 CPU 有 64 字节缓存线,我期望互斥锁 sizeof 为 64,因此可以避免错误共享。大小“仅”40 字节是否有原因?
注意:我知道大小也会影响性能,但程序中很少有大量互斥体,因此与错误共享的成本相比,大小开销似乎可以忽略不计。
注意:有一个类似的问题问为什么 std::mutex 这么大,我问为什么它这么小:)
编辑:MSVC 16.7 的大小为 80。
我从这里知道互斥锁也可以带来内存屏障的效果:Can mutex Replace Memory Barrier,但我总是看到在 C++ 单例示例中使用了内存屏障,如下所示,内存屏障是不必要的吗?
Singleton* Singleton::getInstance() {
Singleton* tmp = m_instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (tmp == nullptr) {
std::lock_guard<std::mutex> lock(m_mutex); // using mutex here
tmp = m_instance.load(std::memory_order_relaxed);
if (tmp == nullptr) {
tmp = new Singleton;
assert(tmp != nullptr);
std::atomic_thread_fence(std::memory_order_release); // using memory barrier here
m_instance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}
Run Code Online (Sandbox Code Playgroud) c++ ×10
stdmutex ×10
c++11 ×2
stdthread ×2
c++20 ×1
clang ×1
destructor ×1
gcc ×1
mutex ×1
optimization ×1
pthreads ×1
stdatomic ×1
visual-c++ ×1
x86 ×1