【问题标题】:pthread_mutex_t VS @synchronized block?pthread_mutex_t VS @synchronized 块?
【发布时间】:2012-02-27 10:33:52
【问题描述】:
static pthread_mutex_t gLock; //global 

pthread_mutex_init(&gLock,NULL); //in init

pthread_mutex_lock(&gLock);
for(int i=0;i<[message count];i++)
CFSetAddValue(mSet, [message objectAtIndex:i]);
pthread_mutex_unlock(&gLock);

我的可可应用程序正在使用 pthread_mutex_t 进入无响应模式。

@synchronized(mSet)
{
for(int i=0;i<[message count];i++)
    CFSetAddValue(mSet, [message objectAtIndex:i]);
}

我的应用程序使用同步块运行良好。

为什么?

【问题讨论】:

    标签: objective-c multithreading cocoa mutex synchronized


    【解决方案1】:

    您将全局锁(所有实例一个锁)与对象级递归锁(每个实例一个锁,可能从同一个线程多次获取)进行比较。它们通常不可互换 - 它们的操作和保护彼此非常不同。

    好消息是,您可以将pthread_mutex_t 用作每个实例唯一的递归锁,以实现与@synchronized 相同的保护程度。使用pthread_mutex_t 还可以使获取锁的速度大大加快。

    要使用 pthread 互斥体达到与@synchronized 相同的效果,请将pthread_mutex_t gLock 声明为实例变量,然后将其初始化为-init 中的递归互斥体。最后,销毁-dealloc中的互斥锁。

    当然,如果子类和基类依赖@synchronized 的语义通过对象层次结构做正确的事情,它们可能需要访问此锁。

    @synchronized 与递归 pthread 互斥锁相比非常慢(我上次检查过)。

    【讨论】:

    • 在 .h 文件中 pthread_mutexattr_t attr; pthread_mutex_t 互斥体;在初始化 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&mutex, &attr);在 dealloc pthread_mutex_destroy(&mutex);在我的函数 pthread_mutex_lock(&mutex); CFSetRemoveAllValues(mySet); pthread_mutex_unlock(&mutex);这样好吗?
    • @ParagBafna a) 互斥锁属性可以是static,并用于您创建的每个互斥锁 - 或非静态且仅用于-init b) 互斥锁属性不必是 ivar c) 你应该验证你的结果代码 d) 在某些情况下你可能更喜欢pthread_mutex_trylock。 e)您应该使用初始化程序初始化结构。除此之外,看起来不错!准备快速锁定 =)
    • 结果代码主要用于检测锁定和线程错误。
    • pthread_mutex_lock 和 pthread_mutex_unlock 返回错误代码 22
    • 我忘了写 pthread_mutexattr_init(&attr);在 init 中,现在它工作正常。我也在其他类中使用相同的 CFMutableSet,我该怎么办?
    【解决方案2】:

    贾斯汀是对的;然而,还有另一个细节,那就是异常处理。从 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html 来此提示:

    作为预防措施,@synchronized 块隐式地向受保护的代码添加异常处理程序。如果抛出异常,此处理程序会自动释放互斥锁。这意味着为了使用 @synchronized 指令,您还必须在代码中启用 Objective-C 异常处理。如果您不希望隐式异常处理程序带来额外的开销,您应该考虑使用锁类。

    如果[message count] 可以引发异常,这些异常可能会跳过您的解锁代码并让您陷入困境。

    【讨论】:

    • ……如果你能恢复的话。大多数 Cocoa 异常是不可恢复的(至少,如果您希望此后执行可预测)。可恢复异常的常见情况是 c++(可预测恢复)。
    猜你喜欢
    • 2014-02-01
    • 2013-06-10
    • 2015-03-25
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-03
    • 1970-01-01
    相关资源
    最近更新 更多