C++静态函数和线程安全
C++ Static functions and thread safety
好吧,我在万能的谷歌上搜索了一些适合我问题的清晰答案,但没有成功。我正在C++中开发一个硬件抽象层,通过各种串行协议(SPI、I2C、UART(进行通信,我在板上有很多需要控制的IC。每个IC都有自己的类。由于我是通过类来建模硬件的,所以我认为在我的代码中拥有与板上安装的IC数量相同的实例数量对我来说很重要。我的问题是:我需要控制这些实例的创建。我提出的解决方案是将无形内容存储在静态std::映射中,该映射以std::字符串为密钥(例如,我使用SPI的设备名称和I2C的地址(。代码如下:
IC.h
class SomeICMap {
private:
static std::map<std::string addr, std::shared_ptr<IC> > instance_map;
public:
static IC* getInitializedInstance(std::shared_ptr<CommInterface> comm, const std::string& addr);
}
IC.cpp
std::map<std::string addr, std::shared_ptr<IC> > instance_map;
IC* SomeICMap::getInitializedInstance(std::shared_ptr<CommInterface> comm, const std::string& addr) {
std::map<string, std::shared_ptr<IC> >::iterator it;
it = instance_map.find(addr);
if (it == instance_map.end()) {
std::shared_ptr<IC> device(new IC(comm, addr));
if (device->init() != 0) {
return NULL;
}
instance_map[addr] = device;
return device.get();
}
return it->second.get();
}
这样我就不会得到安装在板上的硬件的重复实例。我为每个IC都这样做。
我的问题是:这个线程安全吗
我将在Linux下运行的多个线程中使用其中一些IC。我不确定这是否安全,因为我正在访问一个静态映射来获取指针并访问硬件。根据我在网上读到的内容,对硬件的实际访问是安全的,因为内核在使用write((read((操作打开的文件描述符时会考虑并发性。我担心的是当程序第一次创建IC实例时会出现竞争条件。
SomeICMap::getInitializedInstance
不是线程安全的:某个线程可能在另一个线程修改instance_map
时访问它。这是一个数据竞赛,C++不会为具有数据竞赛的程序定义行为。您可以通过向类中抛出一个互斥对象来解决这个问题,并确保在持有互斥对象时执行对映射的所有访问:
class SomeICMap {
private:
static std::map<std::string addr, std::shared_ptr<IC> > instance_map;
static std::mutex mtx; // <-------
public:
static IC* getInitializedInstance(std::shared_ptr<CommInterface> comm,
const std::string& addr);
};
std::map<std::string addr, std::shared_ptr<IC> > SomeICMap::instance_map;
std::mutex SomeICMap::mtx; // <-------
IC* SomeICMap::getInitializedInstance(std::shared_ptr<CommInterface> comm,
const std::string& addr) {
std::lock_guard<std::mutex> lock(mtx); // <-------
std::map<string, std::shared_ptr<IC> >::iterator it;
it = instance_map.find(addr);
if (it == instance_map.end()) {
std::shared_ptr<IC> device(new IC(comm, addr));
if (device->init() != 0) {
return NULL;
}
instance_map[addr] = device;
return device.get();
}
return it->second.get();
}
如果您同时从多个线程调用getInitializedInstance
,那么不,这不是线程安全的。原因是map
插入可能与另一插入或读取交织。
一个简单的解决方案是向类添加一个静态std::mutex
,并在函数开始时围绕它构造一个unique_lock
。
- 从不同线程使用int64的不同字节安全吗
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 在std::thread中,joinable()然后join()线程安全吗
- 在c++队列中使用pop和visit实现线程安全
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- 线程安全运算符<<
- 如何使缓存线程安全
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 提升精神 V2 Qi 语法线程安全吗?
- 线程调用的函数对对象删除是否安全?
- asio 链对象线程安全吗?
- 线程安全队列 c++
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 有没有更好的方法可以使此代码线程安全?线程局部静态似乎是一个生硬的工具