【问题标题】:Acquire a read/write lock if not already held如果尚未持有,则获取读/写锁
【发布时间】:2019-03-16 22:41:38
【问题描述】:

在 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() 的指针。

我将如何解决这个问题?

【问题讨论】:

    标签: multithreading glib


    【解决方案1】:

    第一件事:您要查找的单词是“recursive”。

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

    如果您深入了解实现,您会发现在 POSIX 上,GRWLock 是使用 pthread_rwlock_t、which needn't be recursive 实现的(“如果调用线程持有读写锁,则结果未定义(是否一个读或写锁)在调用时。”)。所以基本上不,GRWLock 对于写入器锁不是递归的。

    至于如何解决您的问题,我的第一个建议是让mess_with_data 和mess_with_data_again 自己获取和释放锁。请记住,您应该只在必要时持有锁,而不再持有。

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

    也可以重构mess_with_data 和mess_with_data_again,这样它们就不需要锁了,但这可能会也可能不会,而且可能相当困难。

    【讨论】:

      猜你喜欢
      • 2019-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多