我可以在std :: shared_mutex上使用std :: shared_lock更改数据吗?

问题描述 投票:0回答:1

我有多个与多个读取器/写入器线程共享的缓冲区,并且不同的写入器以不同的方式更改数据。

例如,Writer1仅追加新数据,而Writer2扩展缓冲区的大小(重新分配内存和移动数据)。

如果我放置单个互斥锁来同步对数据的所有访问,则性能可能不会更好,因为大多数读取器只需要读取单个缓冲区,而大多数写入器只需要向单个缓冲区中写入少量数据即可。 。

如果我为每个缓冲区准备一个互斥量,则线程之间的锁定/解锁关系将更加复杂。

现在我要确认一件事:如果编写者仅使用互斥锁上的shared_lock更改数据,其他人是否会在同一互斥锁上看到带有unique_lock的脏数据?

我编写了如下的实验程序,看起来没有错误,但是我仍然不敢在产品中使用它。

atomic_bool    g_abShouldRun = true;
sem_t          g_semDoIt1;
sem_t          g_semDone1;
sem_t          g_semDoIt2;
sem_t          g_semDone2;
shared_mutex   g_mutex;
int g_iX = 3, g_iY = 9, g_iR1 = 1, g_iR2 = 3;

void writer() {
   std::srand( 8 );

   while( g_abShouldRun ) {
      sem_wait( &g_semDoIt1 );
      while( rand() % 8 != 0 )
         ;

      {
         shared_lock<shared_mutex> lk( g_mutex );
         g_iX *= 2;
         g_iY *= 2;
      }
      sem_post( &g_semDone1 );
   };
};

void reader() {
   std::srand( 8 );

   while( g_abShouldRun ) {
      sem_wait( &g_semDoIt2 );
      while( rand() % 8 != 0 )
         ;

      {
         unique_lock<shared_mutex> lk( g_mutex );
         g_iR1 = g_iX;
         g_iR2 = g_iY;
      }
      sem_post( &g_semDone2 );
   };
};

int main( int argc, char** argv ) {
   int iLasting = 10, iError = 0;
   if( argc > 1 )
      iLasting = atoi( argv[1] );
   steady_clock::time_point tpEnd = steady_clock::now() + seconds( iLasting );

   if( sem_init( &g_semDoIt1, 0, 0 ) || sem_init( &g_semDone2, 0, 0 ) ||
         sem_init( &g_semDoIt2, 0, 0 ) || sem_init( &g_semDone2, 0, 0 ) ) {
      cerr << "Failed to create semaphors." << endl;
      return EXIT_FAILURE;
   }

   thread thd1( writer );
   thread thd2( reader );

   while( steady_clock::now() < tpEnd ) {
      sem_post( &g_semDoIt1 );
      sem_post( &g_semDoIt2 );
      sem_wait( &g_semDone1 );
      sem_wait( &g_semDone2 );
      if( g_iR1 * 3 != g_iR2 )
         ++iError;
   }
   g_abShouldRun = false;
   sem_post( &g_semDoIt1 );
   sem_post( &g_semDoIt2 );
   thd1.join();
   thd2.join();
   sem_destroy( &g_semDoIt1 );
   sem_destroy( &g_semDoIt2 );
   sem_destroy( &g_semDone1 );
   sem_destroy( &g_semDone2 );
   cout << "Error:" << iError << endl;
   return EXIT_SUCCESS;
};
c++ multithreading locking mutex memory-barriers
1个回答
0
投票

以下问题迅速显现出来:

  1. 写入时更改代码以使用unique_lock
  2. 阅读时将代码更改为使用shared_lock
  3. [,请不要修改其他公共全局变量,实际上是在不同的地方进行书写;多少个{shared_mutex,使用unique_lock的函数,使用shared_lock的函数}元组,您将在多个线程和多个缓冲区中使用,您需要弄清楚自己-但这会在1和缓冲区数之间。
© www.soinside.com 2019 - 2024. All rights reserved.