【问题标题】:Best equivalent for EnterCriticalSection on Mac OS X?Mac OS X 上 EnterCriticalSection 的最佳等效项?
【发布时间】:2014-07-02 14:36:33
【问题描述】:

什么是最好的等价物?对于这么简单的功能,我没有找到任何合理的解决方案。我知道的选择:

1) MPEnterCriticalRegion - 不幸的是,这非常无效,可能是因为尽管它的名字它进入内核模式,所以对于重复锁定它只需要太多时间......

2) OSSpinLockLock - 不可用,因为显然不是递归的。如果它是递归的,它将是正确的等价物。

3) pthread_mutex_lock - 没有尝试过,但我并不期待太多,因为它可能只是使用关键区域或其他系统资源来模拟。

【问题讨论】:

  • 您可以轻松地围绕非递归锁生成递归包装器,所以如果您的摘要正确,我猜#2。
  • 怎么样?我正在考虑它,但最后我必须开始比较线程 ID 等......似乎比我最初想象的要复杂。
  • 是的,如果线程获得锁,您必须比较线程 ID 并存储所有者 TID,就是这样。 10 行额外代码顶部。
  • 好吧,我不确定它是否那么简单:1)如果线程 ID 匹配 -> 好的,没有什么问题。 2)如果线程ID不匹配->问题,因为多个线程可能做同一件事,地狱存储的线程ID甚至可能处于部分未确认状态,因此在极端情况下即使不匹配也可能匹配实际上匹配。 -> 所以我需要多一把锁来保护测试代码。现在的问题是,如果不会有额外的问题......

标签: multithreading macos performance critical-section


【解决方案1】:

假设您有一个正常工作的非递归锁,那么获得一个高效的递归锁相当容易(不了解 Mac API,所以这是伪代码):

class RecursiveLock {
public:
    void acquire() {
        auto tid = get_thread_id();
        if (owner == tid) { 
            lockCnt++;
        } else {
            AcquireLock(lock);
            owner = tid;
            lockCnt = 1;
        }
    }

    void release() {
        assert(owner == get_thread_id());
        lockCnt--;
        if (lockCnt == 0) {
            owner = 0;  // some illegal value for thread id
            ReleaseLock(lock);
        }
    }

private:
    int lockCnt;
    std::atomic<void*> owner;  
    void *lock;   // use whatever lock you like here
};

道理很简单:

  • 如果tid == owner 保证我们已经获得了锁。
  • 如果tid != owner 或者其他人持有锁或者它是空闲的,在这两种情况下我们都会尝试获取锁并阻塞直到我们得到它。获得锁后,我们将所有者设置为 tid。所以有一段时间我们获得了锁,但owner 仍然是非法的。但没问题,因为非法 tid 也不会与任何真实线程的 tid 比较,因此它们也会进入 else 分支,并且必须等待获取它。

注意std::atomic 部分 - 我们确实需要为owner 字段提供订购保证以使其合法。如果您没有 c++11,请为此使用一些编译器。

【讨论】:

  • 啊啊啊,你是对的!我把事情复杂化了!谢谢!
  • @Vojtěch 如果没有非法线程 id 值,您还需要一个额外的布尔值。在这种情况下,bool 必须是原子的(准确地说是获取发布语义)并设置 所有者 tid 之后获取,这也不是什么大问题。
  • 为什么所有者需要是原子的,如果它只被所有者线程修改a)和b)当所有者线程拥有锁,并且,它可以设置为平等所有者的唯一方法是获得锁后由所有者自己?
  • @mwag 因为我们同时读取和写入变量。并且读取线程在读取之前不会获取锁,因此锁的内存顺序保证是无用的,所以我们无论如何都需要这些。
猜你喜欢
  • 2011-03-28
  • 1970-01-01
  • 2010-11-29
  • 2010-09-05
  • 1970-01-01
  • 2010-10-08
  • 1970-01-01
  • 2012-06-06
  • 1970-01-01
相关资源
最近更新 更多