c++ 当其他线程使用shared_ptr为共享数据写操作时,读线程的多线程安全

bcs8qyzn  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(192)
  1. class Buffer{
  2. public:
  3. Buffer()=default;
  4. void write(int id) {
  5. std::unique_lock<std::mutex> lck(mtx);
  6. // update data
  7. if (database.find(id) != database.end()) {
  8. std::shared_ptr<Data> data = database.at(id);
  9. data->update(/* something*/);
  10. }
  11. // create new data
  12. else {
  13. std::shared_ptr<Data> new_data = std::make_shared<Data>();
  14. new_data->update(/* something */)
  15. database[id] = new_data;
  16. }
  17. }
  18. shared_ptr<Data> read(int id) {
  19. std::unique_lock<std::mutex> lck(mtx);
  20. std::shared_ptr<Data> data;
  21. // get data if exists
  22. if (database.find(id) != database.end()) {
  23. data = database[id];
  24. }
  25. return data;
  26. }
  27. private:
  28. std::mutex mtx;
  29. std::map<int, shared_ptr<Data>> database;
  30. };

我有一个Buffer类,伪代码在上面.在我的代码中,我有一个线程通过write()不断写入缓冲区,其他线程通过auto data = buffer.read()读取缓冲区。

我的问题是:data将有损坏的性能,因为data可能是写在另一个线程?

nnsrf1az

nnsrf1az1#

在所提供的代码中,为什么只阻止一个线程的读取操作,读取可以并发完成。下面的代码可以改善读取操作。

  1. class Buffer{
  2. public:
  3. Buffer()=default;
  4. void write(int id) {
  5. std::unique_lock<std::shared_mutex> lck(mtx);
  6. // update data
  7. if (database.find(id) != database.end()) {
  8. std::shared_ptr<Data> data = database.at(id);
  9. data->update(/* something*/);
  10. }
  11. // create new data
  12. else {
  13. std::shared_ptr<Data> new_data = std::make_shared<Data>();
  14. new_data->update(/* something */)
  15. database[id] = new_data;
  16. }
  17. }
  18. shared_ptr<Data> read(int id) {
  19. std::shared_lock<std::shared_mutex> lck(mtx);
  20. std::shared_ptr<Data> data;
  21. // get data if exists
  22. if (database.find(id) != database.end()) {
  23. data = database[id];
  24. }
  25. return data;
  26. }
  27. private:
  28. std::shared_mutex mtx;
  29. std::map<int, shared_ptr<Data>> database;
  30. };

所以write()函数仍然可以使用std::unique_lock获取排他锁,以确保一次只有一个线程可以写入。
但是read()函数使用std::shared_lock获取共享锁,允许多个线程并发读取。
通过使用std::shared_mutex,多个线程可以安全地同时从共享资源中读取,但写入需要独占访问。
虽然要回答您的问题,即使您当前的代码也不应该有数据损坏,因为readwrite中的共享数据都是唯一锁定的。

展开查看全部

相关问题