Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading Mac OS X上EnterCriticalSection的最佳等效版本?_Multithreading_Macos_Performance_Critical Section - Fatal编程技术网

Multithreading Mac OS X上EnterCriticalSection的最佳等效版本?

Multithreading Mac OS X上EnterCriticalSection的最佳等效版本?,multithreading,macos,performance,critical-section,Multithreading,Macos,Performance,Critical Section,最好的等价物是什么?对于这样一个简单的函数,我没有找到任何合理的解决方案。我知道的选择: 1) MPInterCriticalRegion-不幸的是,这是非常无效的,可能是因为尽管它的名称不同,它仍进入内核模式,所以对于重复锁来说,它只需要花费太多的时间 2) OSSpinLockLock-不可用,因为显然不是递归的。如果它是递归的,那么它就是正确的等价物 3) pthread\u mutex\u lock-没有尝试,但我没有期望太多,因为它可能只是使用关键区域或其他系统资源进行模拟。假设您有一

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

1) MPInterCriticalRegion-不幸的是,这是非常无效的,可能是因为尽管它的名称不同,它仍进入内核模式,所以对于重复锁来说,它只需要花费太多的时间

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


3) pthread\u mutex\u lock-没有尝试,但我没有期望太多,因为它可能只是使用关键区域或其他系统资源进行模拟。

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

类递归锁{
公众:
无效获取(){
自动tid=获取线程id();
如果(所有者==tid){
lockCnt++;
}否则{
获取锁(lock);
货主=工业贸易署;
lockCnt=1;
}
}
无效释放(){
断言(owner==get_thread_id());
lockCnt--;
如果(lockCnt==0){
owner=0;//线程id的某些非法值
释放锁(锁);
}
}
私人:
int lockCnt;
原子所有者;
void*lock;//在这里使用您喜欢的任何锁
};
道理很简单:

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

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

您可以很容易地围绕非递归锁生成递归包装器,因此如果您的摘要是正确的,我猜是#2。如何?我正在考虑,但最后我不得不开始比较线程ID等。。。看起来比我最初想象的要复杂。是的,如果一个线程获得了锁,你必须比较线程ID并存储所有者TID,就是这样。10行额外代码。好吧,我不确定它是否那么简单:1)如果线程ID匹配->ok,没有什么问题。2) 如果线程ID不匹配->问题,因为多个线程可能处理相同的事情,所以存储的线程ID甚至可能处于部分未确认状态,因此在极端情况下,即使它实际上不匹配,它也可能匹配。->所以我需要多一个锁来保护测试代码。现在的问题是,如果没有其他问题……啊啊啊,你是对的!我把事情搞得太复杂了!谢谢大家!@Vojtěch如果没有非法的线程id值,那么还需要一个额外的bool。在这种情况下,bool必须是原子的(确切地说是acquire-release语义),并在所有者tid之后设置,这也没什么大不了的。为什么所有者需要是原子的,如果它只被所有者线程修改a)和b),而所有者线程拥有锁,并且,唯一可以将其设置为equal owner的方法是在获取锁后由所有者自己设置?@mwag,因为我们同时读取和写入变量。读取线程在读取之前不会获取锁,因此锁的内存顺序保证是无用的,因此我们在任何情况下都需要这些保证。
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
};