21xrx.com
2024-12-23 00:11:29 Monday
登录
文章检索 我的文章 写文章
C++ 线程安全的 vector 实现
2023-06-27 18:15:17 深夜i     --     --
C++ 线程安全 vector 实现 并发控制

C++中的vector是一种非常常用的数据结构,它可以在动态数组上提供许多操作。但是,当多个线程同时读取或修改这个共享的容器时,会出现线程安全问题。因此,线程安全的vector实现非常重要。

C++11提供了一种名为std::mutex的线程锁,用于控制多个线程对共享资源的访问。因此,标准库中的vector可以通过加锁和解锁来控制并发线程的操作。但是,由于这种方法的效率很低,我们需要探索更有效的方法,同时保持线程安全。

我们可以使用STL中的std::atomic实现线程安全的vector。std::atomic是C++11中的一个模板类,用于实现线程安全的操作。std::atomic可以确保多个线程对变量的访问不会产生竞争条件。std::atomic可以通过fetch_add()和fetch_sub()等方法,原子性地增加或减少指定值。

在使用std::atomic实现线程安全的vector时,我们需要将vector的大小、容量和数据指针都声明为std::atomic类型。例如:


template<typename T>

class ThreadSafeVector {

public:

  ThreadSafeVector() : size(0), capacity(0), data(nullptr) {}

  void push_back(const T& value) {

   std::unique_lock<std::mutex> lock(mtx);

   if(size >= capacity) {

     size_t new_capacity = (capacity == 0) ? 1 : 2*capacity;

     T* new_data = new T[new_capacity];

     for(size_t i = 0; i < size; ++i) {

      new_data[i] = data[i];

     }

     delete[] data;

     capacity = new_capacity;

     data = new_data;

   }

   data[size++] = value;

  }

  T& operator[](size_t index) {

   return data[index];

  }

  const T& operator[](size_t index) const {

   return data[index];

  }

  size_t getSize() const {

   return size.load();

  }

  bool empty() const {

   return size.load() == 0;

  }

private:

  std::mutex mtx;

  std::atomic<size_t> size;

  std::atomic<size_t> capacity;

  std::atomic<T*> data;

};

在以上代码中,我们将vector的大小、容量和数据指针都声明为std::atomic类型。使用std::atomic类型的好处是,在一个线程操作这些变量时,其他线程无法对其进行修改,并且操作是原子性的。

在push_back操作中,我们使用std::unique_lock lock(mtx)语句来加锁和解锁。在锁定期间,其他线程不能修改数据。

在getSize和empty操作中,我们使用size.load()语句来获得std::atomic size的当前值。在这里,std::atomic类型允许我们原子性地读取变量的值,而不需要加锁和解锁。

使用std::atomic实现线程安全的vector虽然比使用std::mutex更复杂一些,但是可以大大提高效率,同时保持线程安全。因此,在多线程环境中,我们应该考虑使用线程安全的vector实现。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复