如何确定线程是否有锁?

时间:2011-04-23 18:33:45

标签: objective-c c pthreads posix readwritelock

我正在编写一个Objective-C类,我希望它是线程安全的。要做到这一点,我使用pthreads和pthread_rwlock(使用@synchronized是过度的,我想学习更多关于pthreads)。锁定在指定init方法的对象中,并在dealloc中销毁。我有三种操作锁的方法; readLockwriteLockunlock。这三种方法只调用相关的pthread函数,目前没有其他任何东西。

以下是两个对象方法,两者都需要writeLock:

-(void)addValue:(const void *)buffer
{
    [self writeLock];

    NSUInteger lastIndex = self.lastIndex;
    [self setValue:buffer atIndex:(lastIndex == NSNotFound) ? 0 : lastIndex+1];

    [self unlock];
}


-(void)setValue:(const void *)buffer atIndex:(NSUInteger)index
{
    [self writeLock];
    //do work here
    [self unlock];
}

调用setAddValue:将首先获得写锁定,然后调用setValue:atIndex:,它还将尝试获取写锁定。文档指出发生这种情况时行为未定义。因此,在尝试获取锁之前,如何检查线程是否有锁?

(我可以确保关键部分不会调用触发另一个锁定请求,但这意味着代码重复,我想让我的代码保持DRY)。

3 个答案:

答案 0 :(得分:2)

不完全清楚你正在使用什么样的锁。你表明你正在使用pthreads和读/写锁,所以我得出的结论是你正在使用pthread_rwlock。

如果这是真的,那么你应该可以在锁上使用pthread_rwlock_trywrlock。从手册页中,

如果成功,则pthread_rwlock_wrlock()和pthread_rwlock_trywrlock() 函数将返回零。否则,将返回错误号 表示错误。

并且,其中一个错误是:

[EDEADLK]调用线程已拥有读/写锁                    (用于阅读或写作)。

因此,我相信您应该能够致电pthread_rwlock_trywrlock()并且您将获得成功,如果另一个线程有锁定,它将返回EBUSY,否则您将获得EDEADLK当前线程有锁。

答案 1 :(得分:0)

首先,仅包含一个操作的关键部分是无用的。关键是要使不同的事物相互同步。 (你确实有效地使整数成为原子,但这可能不是完整的意图。)

其次,您已经知道在后一个关键部分中有写锁定,因此无需检查它是否存在。只是在写作时不要尝试读锁定。

解决方案可能是将readLockwriteLock调用移动到调用函数中,但不知道更多内容是不可能的。

(这也可能通过减少总操作次数来降低锁定的性能成本,因为您不会锁定然后立即解锁。可能您不需要直接在pthreads级别工作。)

答案 2 :(得分:0)

便携式程序不能依赖于实现来告诉调用者它已经拥有写锁定。相反,您需要执行类似这样的操作来使用递归写锁来包装rwlock:

int wrlock_wrap(pthread_rwlock_t *l, int *cnt)
{
    int r = *cnt ? 0 : pthread_rwlock_wrlocK(l);
    if (!r) ++*cnt;
    return r;
}

int wrunlock_wrap(pthread_rwlock_t *l, int *cnt)
{
    --*cnt;
    return pthread_rwlock_unlock(l);
}

您可以将计数保留在pthread_rwlock_t旁边的任何位置,例如作为struct / class /的成员。