首页 > 解决方案 > 强大的互斥锁不适用于共享内存

问题描述

我正在使用在这里找到的内存共享互斥锁的实现:https ://gist.github.com/yamnikov-oleg/abf61cf96b4867cbf72d

如果持有锁的进程崩溃,我担心互斥锁所有权的行为。从我的测试来看,其他进程似乎无法获得锁。我在搜索时发现了健壮互斥锁的概念,并通过更改这部分来修改代码:

  // If shared memory was just initialized -
  // initialize the mutex as well.
  if (mutex.created) {
    pthread_mutexattr_t attr;
    if (pthread_mutexattr_init(&attr)) {
      perror("pthread_mutexattr_init");
      return mutex;
    }
    if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
      perror("pthread_mutexattr_setpshared");
      return mutex;
    }
    if (pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)) { //Added this portion.
      perror("pthread_mutexattr_setrobust");
      return mutex;
    }
    if (pthread_mutex_init(mutex_ptr, &attr)) {
      perror("pthread_mutex_init");
      return mutex;
    }
  }

使用这些文件的代码是:

  shared_mutex_t mutex = shared_mutex_init("/my-mutex");

  if (mutex.ptr == NULL) return 1;

  if (mutex.created) printf("The mutex was just created\n");
  int i = 0;
  while(1) {
    int trylock = pthread_mutex_trylock(mutex.ptr);
    printf("Try lock: %d\n", trylock);
    if (trylock != 0) continue;

    printf("I'm in\n");

    if (i == 5) {
      return 1 / 0;
    }

    sleep(5);    
    pthread_mutex_unlock(mutex.ptr);
    sleep(1);

    i++;
    if (i == 10) {
      break;
    }
  }

为了进行测试,我运行了两个程序实例并观察它们之间传递的锁所有权。当 i == 5 时,程序将中断,并且应该将所有权传递给下一次调用 lock,从我所读到的健壮互斥锁中。

但是,似乎没有任何改变,并且行为与我更改任何内容之前相同。关于如何进行的任何想法?提前致谢。

编辑:

使用pthread_mutex_trylock为程序提供正确的行为。似乎在其中创建的“my-mutex”文件包含/dev/shm了我在以前的尝试中使用的互斥锁的实例,其中不包括我后来更改的健壮设置。删除它并使用上述函数运行使其返回 OWNERDEAD 并且进程能够锁定互斥锁。

标签: cpthreadsposixmutexshared-memory

解决方案


文档说

由 mutex 引用的 mutex 对象应通过 pthread_mutex_lock()返回零或的调用来锁定[EOWNERDEAD]

您没有[OWNERDEAD]正确处理返回代码,因此您错过了互斥锁的重新锁定。

有关如何处理的更多信息:

如果互斥锁是一个健壮的互斥锁并且拥有线程在持有互斥锁时终止,则即使拥有线程所在的进程尚未终止,调用也pthread_mutex_lock()可能返回错误值。[EOWNERDEAD]在这些情况下,互斥锁被线程锁定,但它保护的状态被标记为不一致。应用程序应确保状态保持一致以便重用以及何时完成调用pthread_mutex_consistent()。如果应用程序无法恢复状态,它应该在没有事先调用的情况下解锁互斥锁pthread_mutex_consistent(),之后互斥锁被标记为永久不可用。


推荐阅读