Object C++;11只能将原始数据类型声明为原子数据类型吗?
我想知道,在C++11中只能声明原始数据类型std::atomic吗?有没有可能,比如说,声明一个库类对象被“原子地”变异或访问 例如,我可能有Object C++;11只能将原始数据类型声明为原子数据类型吗?,object,c++11,thread-safety,mutex,atomic,Object,C++11,Thread Safety,Mutex,Atomic,我想知道,在C++11中只能声明原始数据类型std::atomic吗?有没有可能,比如说,声明一个库类对象被“原子地”变异或访问 例如,我可能有 using namespace std::chrono; time_point<high_resolution_clock> foo; // setter method void set_foo() { foo = high_resolution_clock::now(); } // getter method time_point
using namespace std::chrono;
time_point<high_resolution_clock> foo;
// setter method
void set_foo() {
foo = high_resolution_clock::now();
}
// getter method
time_point<high_resolution_clock> get_foo() {
return foo;
}
使用名称空间std::chrono;
时间点foo;
//塞特法
void set_foo(){
foo=高分辨率时钟::现在();
}
//吸气剂法
时间点获取时间点{
返回foo;
}
但是,如果在不同的线程中调用这些setter和getter方法,我认为这可能会导致未定义的行为。如果我可以声明foo类似于:
std::atomic<time_point<high_resolution_clock>> foo;
std::原子foo;
…这样所有关于foo的行动都将以原子方式进行。在我项目的应用程序中,可能有数百个这样的foo变量在几十个类中声明,我觉得让对象变异并访问“原子”会更方便,而不必到处声明和锁定互斥锁
这是不可能的,还是有更好的方法,或者我真的必须在任何地方使用互斥锁和锁保护
更新:
- 有人要吗?我一直在网络上寻找合适的信息,但是使用atomic的例子太少了,我不能确定它的应用范围 原子的
不限于基本类型。允许将atomic
与类型T
一起使用,即。根据c++11标准第29.5节原子类型(也在中说明):
有一个通用类模板原子。模板参数T的类型应该是可复制的(3.9)
如果需要原子访问的对象不能与atomic
一起使用,则定义新对象,其中包含原始对象和std::mutex
。这意味着,lock\u-guard
仅在新线程安全对象的getter和setter中使用,并且不会在整个代码中乱放。模板
可能能够定义所需的螺纹安全机构:
template <typename T>
class mutable_object
{
public:
mutable_object() : t_() {}
explicit mutable_object(T a_t) : t_(std::move(a_t)) {}
T get() const
{
std::lock_guard<std::mutex> lk(mtx_);
return t_;
}
void set(T const& a_t)
{
std::lock_guard<std::mutex> lk(mtx_);
t_ = a_t;
}
private:
T t_;
mutable std::mutex mtx_;
};
using mutable_high_resolution_clock =
mutable_object<std::chrono::time_point<
std::chrono::high_resolution_clock>>;
using mutable_string = mutable_object<std::string>;
mutable_high_resolution_clock c;
c.set(std::chrono::high_resolution_clock::now());
auto c1 = c.get();
mutable_string s;
s.set(std::string("hello"));
auto s1 = s.get();
模板
类可变对象
{
公众:
可变_对象():t_u(){}
显式可变_对象(T a_T):T_(std::move(a_T)){
T get()常量
{
标准:锁紧保护lk(mtx);
返回t_;
}
空集(常数和空集)
{
标准:锁紧保护lk(mtx);
t_u=a_ut;
}
私人:
T!;
可变std::互斥mtx;
};
使用可变高分辨率时钟=
可变对象>;
使用可变_字符串=可变_对象;
可变高分辨率时钟c;
c、 set(std::chrono::high_resolution_clock::now());
自动c1=c.get();
可变_字符串;
s、 set(std::string(“hello”);
自动s1=s.get();
原子仅限于可复制的类(即没有自定义复制构造函数的类,其成员也可复制)
这一要求对原子具有巨大的优势:
- 没有原子操作可以抛出,因为构造函数抛出了
- 所有原子都可以用锁(自旋锁或互斥锁)和memcpy来复制数据
- 所有原子都有一个有限的运行时间(有界)
后者特别有用,因为原子有时是使用自旋锁实现的,并且非常希望在持有自旋锁时避免无界任务。如果允许使用任何构造函数,那么实现往往需要依赖于完整的互斥锁,对于非常小的关键部分,互斥锁比自旋锁慢。std::atomic对于断开的线程代码来说不是一种解决方法。如果另一个线程调用setter,那么不管第一个线程调用什么,它都将从getter获取一个垃圾值。