多进程多线程共享内存环境中pthread读写锁的意外行为

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

我在多进程、多线程环境中工作,使用存储在共享内存中的

pthread_rwlock_t
读写锁,以便所有进程都可以访问它。这是我最初初始化锁的方式:

rw_lock = (pthread_rwlock_t *) ShmemAlloc(sizeof(pthread_rwlock_t));
if(pthread_rwlock_init(rw_lock, NULL)) {
    // Handle error
}

在此设置中,进程 A 获取读锁,如下所示:

lockStatus = pthread_rwlock_tryrdlock(rw_lock);
switch(lockStatus) {
    case 0:
        break;
    case EBUSY:
        for(int i = 0; i < 10000; i++) {
            pg_usleep(100);
            lockStatus = pthread_rwlock_tryrdlock(rw_lock);
            if(!lockStatus) {
                break;
            }
        }

        if(!lockStatus) {
            break;
        }
    case EINVAL:
    default:
        printf(ERROR, "COULD NOT GET SHARED LOCK");
        break;
}

进程A获取读锁后,进程B尝试获取独占(写)锁:

if(pthread_rwlock_wrlock(rw_lock)) {
    printf(ERROR, "COULD NOT GET EXCLUSIVE LOCK");
}

我预计一旦进程A释放读锁,进程B就会获得排它锁。 然而,我观察到了意想不到的行为:

  • 有时进程 B 在长时间延迟(5-30 秒)后获取锁。
  • 其他时候,进程 B 根本不会获取排他锁。

阅读文档后,我修改了初始化以传递如下属性:

rw_lock = (pthread_rwlock_t *)ShmemAlloc(sizeof(pthread_rwlock_t));
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);

if(pthread_rwlock_init(rw_lock, &attr)) {
    pthread_rwlockattr_destroy(&attr);
    // Handle error
}

通过此更改,在进程 A 释放读锁后,进程 B 会如预期一致地获取排它锁。

我的问题:

  1. 在最初的场景中(没有
    PTHREAD_PROCESS_SHARED
    ),进程B如何知道进程A持有共享锁?是在等待某种内部机制吗?
  2. 为什么进程 B 在第二个场景(
    PTHREAD_PROCESS_SHARED
    )中意识到锁被释放,而不是在第一个场景中?
    pthread
    库如何向其他进程发出锁已释放的信号?

任何有关

pthread_rwlock
的内部行为及其跨流程工作方式的见解将不胜感激。

c synchronization pthreads locking
1个回答
2
投票
  1. 在最初的场景中(没有
    PTHREAD_PROCESS_SHARED
    ),进程B如何知道进程A持有共享锁?是不是在等待 在某些内部机制上?

未指定或定义。 不过,据推测,它是通过查看共享内存中的锁数据结构来知道的。 在 B 认识到 A 已释放锁的情况下,它大概也以同样的方式知道这一点。 目前尚不清楚它如何知道在注意到状态变化的情况下如何查看。

  1. 为什么进程 B 在第二个场景(
    PTHREAD_PROCESS_SHARED
    )中意识到锁被释放,而不是在第一个场景中?如何
    pthread
    库是否向其他进程发出锁已锁定的信号 被释放了?

锁需要配置为跨进程使用,以便定义多个进程并发使用时的行为。 (这是支持多进程使用的 pthreads 对象的标准。)您在第二个场景中配置了锁,但不是在第一个场景中,因此您在第二个场景中根据锁的规范获得了行为,并在第一个场景中获得了未定义的行为首先。

pthread_rwlock
的内部行为及其如何运作的任何见解 跨流程工作将不胜感激。

Pthreads 首先是一个规范。 有多种实现方式,其内部细节各不相同。 “内部是如何运作的?”对于只想使用实现的人来说很少是一个有用的问题,而且无论如何也没有通用的答案。 一般来说,您应该根据其规范专注于使用 Pthreads 等 API,而不是关注如何实现这些规范的细节。

但是,如果您坚持,您可以研究开源实现的源代码,例如 Glibc 的源代码。

© www.soinside.com 2019 - 2024. All rights reserved.