我从这里知道互斥锁也可以带来内存屏障的效果: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++异常,遇到了麻烦,程序如下
#include<iostream>
#include<unistd.h>
#include<string>
#include<thread>
#include<vector>
#include<exception>
using namespace std;
vector<int> vec(20);
void fn()throw() {
vec.at(10);
}
int main(){
fn();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我使用 gdb 反汇编fn(),我们可以看到callq 0x4008d0 _Unwind_Resume@plt,这是对堆栈展开操作的调用,因为 vector::at 可能会抛出超出范围的异常
Dump of assembler code for function fn():
0x00000000004009e6 <+0>: push %rbp
0x00000000004009e7 <+1>: mov %rsp,%rbp
0x00000000004009ea <+4>: mov $0xa,%esi
0x00000000004009ef <+9>: mov $0x6020a0,%edi
0x00000000004009f4 <+14>: callq 0x400ba6 <std::vector<int, std::allocator<int> >::at(unsigned long)>
0x00000000004009f9 <+19>: jmp 0x400a11 <fn()+43>
0x00000000004009fb <+21>: cmp $0xffffffffffffffff,%rdx
0x00000000004009ff <+25>: je 0x400a09 <fn()+35>
0x0000000000400a01 …Run Code Online (Sandbox Code Playgroud) int main(){
std::mutex mut;
mut.lock();
cout<<"1111\n";
mut.lock();
cout<<"2222\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么这段代码能工作并输出2222?它不应该在第二个 lock() 处阻塞吗?在互斥锁源码中,操作锁抛出异常。它不应该阻塞并等待吗?我try{...}catch(exception& e){}用来捕捉这个异常,但它不起作用。
void
lock()
{
int __e = __gthread_mutex_lock(&_M_mutex);
// EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
if (__e)
__throw_system_error(__e);
}
Run Code Online (Sandbox Code Playgroud)
int main(){
atomic<bool> atomic_lock(false);
std::atomic_flag lock_flag = ATOMIC_FLAG_INIT;
int count = 0;
auto f = [&](){
bool flag = false;
for( int i = 0; i< 10000000; ++i){
while(!atomic_lock.compare_exchange_strong(flag, true)){}
//while(lock_flag.test_and_set(std::memory_order_seq_cst));
++count;
//lock_flag.clear(std::memory_order_seq_cst);
atomic_lock.store(false, std::memory_order_seq_cst);
}
};
thread t1(f);
thread t2(f);
t1.join();
t2.join();
cout<<count<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我的程序,我想用 CAS 替换互斥锁,但不是 20000000 的输出表明它不是线程安全程序,哪里错了?但是,我用 atomic_flag 替换 atomic 显示如上,输出是正确的
我进行了如下测试,创建一个向量并将其容量设置为 1,然后用于v[100]=100;直接分配 v[100] 但不触发核心转储,为什么?向量v应该没有足够的内存来访问v[100],但是v[100]成功被赋值为100,并且size和capacity()保持为0和1,如何理解?
int main(){
std::vector<int> v;
v.reserve(1);
v[100]=100; //here does't triggle core dump, wired
std::cout<<v.size()<<std::endl; //0
std::cout<<v.capacity()<<std::endl; //1
std::cout<<v[100]<<std::endl; //100
return 0;
}
Run Code Online (Sandbox Code Playgroud)