我正在阅读http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html,我仍然不清楚一些线程安全问题:
编辑:
伪代码:
// Thread I
shared_ptr<A> a (new A (1));
// Thread II
shared_ptr<A> b (a);
// Thread III
shared_ptr<A> c (a);
// Thread IV
shared_ptr<A> d (a);
d.reset (new A (10));
Run Code Online (Sandbox Code Playgroud)
在线程IV中调用reset()将删除在第一个线程中创建的A类的先前实例并将其替换为新实例?此外,在IV线程中调用reset()之后,其他线程只会看到新创建的对象?
以下是一些代码段.
std::shared_ptr<int> global(new int(1));
void swapper(int x)
{
std::shared_ptr<int> sp(new int(x));
global.swap(sp);
}
Run Code Online (Sandbox Code Playgroud)
假设我想调用swapper并行线程.这是线程安全的吗?
我知道这个答案.它显示了如果我重新分配值,如何指定指针不是线程安全的global.
我的问题是swap成员函数本身是否是线程安全的.
一方面,shared_ptr的控制块功能是线程安全的.另一方面,我假设我正在切换到控制块的指针,所以它不应该是线程安全的.
有什么联系?是swap线程安全的?
我有指向单例类的指针对象。
线程 1:当前正在执行上述对象的成员函数。
线程 2:当对象的成员函数仍在线程 1 执行时删除上述对象。
正在执行成员函数的线程 1 会发生什么?执行是否会中途停止?
我有两个与此类似的课程:
class Foo {
public:
void bar() {
std::lock_guard<std::mutex> lock(m_mutex);
m_data.push_back('x');
}
private:
std::string m_data;
std::mutex m_mutex;
};
class Pool {
public:
static std::shared_ptr<Foo> Create(int index) {
std::lock_guard<std::mutex> lock(m_mutex);
if (m_pool.size() > 10) {
m_pool.erase(m_pool.begin());
}
std::shared_ptr<Foo>& ptr = m_pool[index];
if (!ptr) ptr.reset(new Foo);
return ptr;
}
private:
static std::mutex m_mutex;
static std::map<int, std::shared_ptr<Foo>> m_pool;
};
Run Code Online (Sandbox Code Playgroud)
和几个运行此代码的线程:
void parallel_function(int index) {
// several threads can get the same index
std::shared_ptr<Foo> foo = Pool::Create(index);
foo->bar();
}
Run Code Online (Sandbox Code Playgroud)
所有成员函数(包括复制构造函数和复制赋值)都可以由共享_ptr 的不同实例上的多个线程调用,而无需额外的同步,即使这些实例是同一对象的副本并共享所有权。如果多个执行线程在没有同步的情况下访问同一个shared_ptr,并且这些访问中的任何一个使用shared_ptr的非常量成员函数,那么就会发生数据竞争;原子函数的shared_ptr重载可用于防止数据竞争。
两个问题: …
在他的伟大着作"C++并发行动"中,Anthony Williams撰写了以下内容(第309页):
例如,在x86和x86-64架构,原子加载操作总是相同的,无论是标记为memory_order_relaxed或memory_order_seq_cst(见第5.3.3节).这意味着使用松散内存排序可在与x86架构,它会在系统上会失败,并finer-晶组内存排序指令,如SPARC系统的工作编写的代码.
我是否认为在x86架构中所有原子加载操作都是正确的memory_order_seq_cst?另外,在cppreference std::memory_order网站上提到在x86发布 - 获取顺序是自动的.
如果此限制有效,那么排序是否仍适用于编译器优化?
从std::shared_ptr 线程安全等文章中,我知道 std::shared_ptr 的控制块按标准保证是线程安全的,而指向的实际数据本质上不是线程安全的(即,它是对我来说,作为用户,做到这一点)。
我在研究中未能找到如何保证这一点的答案。我的意思是,具体使用什么机制来确保控制块是线程安全的(因此对象只被删除一次)?
我问这个问题是因为我正在将 newlib-nano C++ 库与 FreeRTOS 一起用于嵌入式系统。这两者本质上并不是为了相互协作而设计的。由于我从未编写过任何代码来确保控制块是线程安全的(例如,没有关键部分或互斥体的代码),因此我只能假设它实际上可能不是 FreeRTOS 线程安全的。