获取读/写锁(如果尚未持有)

时间:2019-03-16 22:41:38

标签: multithreading glib

在GLib中,是否有一项操作告诉它“如果您尚未持有该锁,则先获取它”?同一线程可以两次获取一个锁(使第二次获取成为无操作,或者要求将其释放两次)或测试它是否已经持有特定的锁?

假设我的代码中具有以下功能:

void func_a() {
    //g_rw_lock_writer_lock(&shared_data->rw_lock);
    mess_with_data(shared_data);
    func_b();
    //g_rw_lock_writer_unlock(&shared_data->rw_lock);
}

void func_b() {
    //g_rw_lock_writer_lock(&shared_data->rw_lock);
    mess_with_data_again(shared_data);
    //g_rw_lock_writer_unlock(&shared_data->rw_lock);
}

假设:

  • shared_data指向共享的数据结构,并且访问需要在线程之间进行同步
  • shared_data->rw_lock是用于同步访问的读/写锁
  • func_a()func_b()均可从外部调用
  • mess_with_data()mess_with_data_again()不是线程安全的,因此调用方需要在对数据进行写锁之前对其进行调用
  • 它们不仅是单个函数调用,而是语句行,因此将func_b()的主体复制到func_a()中不是一种选择(代码重复,可维护性差)
  • func_a()func_b()的调用者无法直接访问该锁,因此需要在后台进行锁定
  • func_b()的函数体(不进行锁定/解锁)提取到func_a()func_()分别调用的单独的辅助函数中是不可行的(它们分散在多个模块之间,并且函数调用之间存在抽象层-实际上,func_a()并不是直接按名称调用func_b(),而是恰好解析为func_b()的指针)。

我该如何解决?

1 个答案:

答案 0 :(得分:1)

首先,要寻找的单词是“ recursive”。

虽然GMutex明确提到互斥体是否是递归的,但AFAIK GRWLock只是忽略了 writer 锁是否是递归的(读者方面)是递归的。)

如果稍微深入了解实现,您会发现在POSIX上GRWLock是使用pthread_rwlock_twhich needn't be recursive实现的(“如果调用线程持有调用时具有读写锁定(无论是读取锁定还是写入锁定)。”)。因此,基本上没有,GRWLock对于写程序锁不是递归的。

关于如何解决您的问题,我的第一个建议是让mess_with_datamess_with_data_again自己获取并释放锁。请记住,您只应将锁保持必要的时间,而不必再保持时间。

如果由于某种原因(例如您可能无法访问该代码)而不选择该选项,则可以使用递归锁,或者将编写器操作限制为一个线程并使用队列与之通信。

还可以重构mess_with_datamess_with_data_again,以便它们不需要锁,但这可能或不可能,而且很困难。