2017-03-04 76 views
1

我在AIX上编写代码,但寻找一个通用的'nix解决方案,posix符合理想。在C++ 11或更高版本中不能使用任何东西。posix:进程间锁被抛弃,有没有更好的方法?

我与许多涉及多个进程的线程共享内存。共享内存中的数据必须保持自我一致,所以我需要一个锁,让每个人轮流。

使用锁定进程崩溃是一件事情,所以我必须能够检测到一个废弃的锁定,修复(又名重置)数据,并继续前进。 Twist:通过等待某个固定时间来决定锁定是否被放弃不是一个可行的解决方案。

一个全局互斥量(无论是居住在共享内存还是命名中)似乎都不是一个解决方案。没有放弃的检测机制(除时间以外),即使如此,您也无法删除并重新构建互斥体,而不会冒未定义的行为。因此我选择了lockf()和一个忙标志 - 获取文件锁定,在共享内存中设置标志,执行任务,取消设置标志,放下锁定。在锁具崩溃时,锁会自动丢弃,然后下一个获得该锁的人可以看到忙标志仍然设置,并且知道他必须清理一团糟。

这不起作用 - 因为lockf()将保留其他进程的线程,但它对于自己的进程中的其他线程有特殊的语义。它可以让他们完全不受限制。

最后我提出了两步解决方案 - 一个本地(线程)互斥锁和一个文件锁。首先获取本地互斥锁;现在你是进行下一步的唯一线程,就是lockf()。 lockf()反过来保证你是唯一通过的进程,所以现在你可以设置忙标志并完成工作。要解锁,请按相反顺序进行操作:清除忙标志,放下文件锁,放下互斥锁。在崩溃时,当进程执行时,本地互斥量消失,因此它是无害的。

工作正常。我讨厌它。使用两个像这样嵌套的锁使我感到昂贵,并且在代码中需要一页值得注释的解释。 (我的下一个代码审查将是有趣的)。我觉得我错过了一个更好的解决方案。它是什么?

编辑:@Matt我可能不清楚。忙标志不是锁定机制的一部分;它表示某个进程何时成功获取了该锁。如果在获取锁之后,您看到忙标志已经设置,这意味着某个其他进程获得了锁并然后崩溃,使处于写入中间的共享内存处于未完成状态。在这种情况下,现在拥有锁的线程可以将共享内存重新初始化为可用状态。我可能应该把它称为“memoryBeingModified”标志。

“tryLock”没有任何变化是允许的。轮询在这个应用程序中绝对不存在。需要修改共享内存的线程可能只会阻塞锁(永远不会很长),并且只要锁可用,就必须轮到它们。他们必须经历最小可能的延迟。

回答

0

你可以

//always returns true unless something horrible happened 
bool lock() 
{ 
    if (pthread_mutex_lock(&local_mutex)==0) 
    { 
     if (lockf(global_fd, F_LOCK, 0)) 
      return true; 
     pthread_mutex_unlock(&local_mutex); 
    } 
    return false; 
} 

void unlock() 
{ 
    lockf(global_fd, F_ULOCK, 0); 
    pthread_mutex_unlock(&local_mutex); 
} 

这看起来非常简单给我,我也不会觉得太糟糕了有关使用2级锁 - 的pthread_mutex是相当快,几乎不消耗资源。

+0

我可能并不清楚。忙标志不是锁定机制的一部分;它表示某个进程何时成功获取了该锁。如果在获取锁之后,您看到忙标志已经设置,这意味着某个其他进程得到了锁,然后崩溃,使正在写入中间的共享内存处于未完成状态。在这种情况下,现在拥有锁的线程可以将共享内存重新初始化为可用状态。 – user15001

+0

啊,好吧,没问题。我将trylock改为lock(),这同样简单。 –

相关问题