最适合Mac OS X上的EnterCriticalSection?

时间:2014-07-02 14:36:33

标签: multithreading macos performance critical-section

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

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

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

3)pthread_mutex_lock - 没试过,但我没想到太多,因为它可能只是使用关键区域或其他系统资源进行模拟。

1 个答案:

答案 0 :(得分:0)

假设你有一个正确工作的非递归锁,它很容易获得一个有效的递归锁(不知道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也不会与任何真正的线程进行比较,所以他们也会进入else分支并且必须等待才能获得它。

请注意std::atomic部分 - 我们需要owner字段的订购保证才能使其合法化。如果你没有c ++ 11,那就使用一些内在的编译器。