Concurrency pthreads锁定方案,允许并发读取共享数据结构

Concurrency pthreads锁定方案,允许并发读取共享数据结构,concurrency,pthreads,mutex,Concurrency,Pthreads,Mutex,假设您有一些既能读取又能写入数据结构的代码。如果有多个线程执行此代码(并共享数据结构),是否有某种安排可以实现以下目标: 允许2次或更多并发读取,不允许写入 不允许2次或更多写入 不允许1个或多个读取与1个或多个写入同时进行 在任何读取和写入过程中锁定的单个互斥锁可以实现目标2和3,但无法实现目标1。有什么解决方案可以实现这三个目标吗 假设不可能设计一种方案,其中数据结构的不同子部分可以使用不同的互斥锁进行保护 我在这方面的笨拙做法是: 每个线程有一个互斥体,每个线程在需要读取时锁定自己的互斥体

假设您有一些既能读取又能写入数据结构的代码。如果有多个线程执行此代码(并共享数据结构),是否有某种安排可以实现以下目标:

  • 允许2次或更多并发读取,不允许写入
  • 不允许2次或更多写入
  • 不允许1个或多个读取与1个或多个写入同时进行
  • 在任何读取和写入过程中锁定的单个互斥锁可以实现目标2和3,但无法实现目标1。有什么解决方案可以实现这三个目标吗

    假设不可能设计一种方案,其中数据结构的不同子部分可以使用不同的互斥锁进行保护

    我在这方面的笨拙做法是:

  • 每个线程有一个互斥体,每个线程在需要读取时锁定自己的互斥体

  • 有一个额外的“全局”互斥。当任何线程想要写入时,它首先锁定这个全局互斥锁。然后,它在所有线程特定的互斥体上执行pthread_mutex_trylock()循环,直到将它们全部锁定,然后执行写操作,然后将它们全部解锁。最后,它打开全局互斥锁

  • 然而,这种方法似乎不是很有效

    提前感谢,


    Henry

    Pthreads包括具有这种行为的读写器锁。您可以以一种分析的方式初始化它们以创建互斥对象-静态方式或:

    pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
    
    或者使用
    pthread\u rwlock\u init()动态执行

    要锁定读取(共享),请使用
    pthread\u rwlock\u rdlock()
    ;要锁定写入(独占),请使用
    pthread\u rwlock\u wrlock()
    。也有“trylock”和“timedlock”的变体


    当然,您也可以从pthreads mutex和condition变量构建这样的锁。例如,您可以将读卡器侧锁实现为:

    pthread_mutex_lock(&mutex);
    readers++;
    pthread_mutex_unlock(&mutex);
    
    写入器侧锁是:

    pthread_mutex_lock(&mutex);
    while (readers > 0)
        pthread_cond_wait(&mutex, &cond);
    
    读卡器侧解锁为:

    pthread_mutex_lock(&mutex);
    if (--readers == 0)
        pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    
    写入端解锁为:

    pthread_mutex_lock(&mutex);
    if (--readers == 0)
        pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    
    (这只是出于兴趣-最好使用内置读写器锁,因为这些锁可以直接使用特定于体系结构的代码实现,这可能比使用其他pthreads原语更有效)


    注意,在一个实际的实现中,你要考虑的是<代码>读者溢出。

    pType支持一个<>代码> pthRead我没有使用它们的经验。谢谢你的回答@caf。这是一个优雅的解决方案。如果我理解你的互斥/cond公式,在
    while(readers>0)pthread\u cond\u wait(&mutex,&cond)
    循环中,
    读卡器可能会增加或减少,因此写入端锁受所有其他线程的支配,而这些线程恰好同时在读取部分之外。@HenryBigelow:是的,读者实际上比作者享有优先权。内置pthreads rwlocks也是如此,因为它们保证读锁是递归的——也就是说,您可以安全地重新锁定已经持有的读锁。如果您让稍后到达的读卡器等待写入器,那么这将导致死锁(除非您对递归情况给予特殊豁免,这需要跟踪每个线程持有的每个读锁,这需要无限的空间)。