iOS 中的各种锁

2019-03-06  本文已影响0人  含笑州

简单的性能测试

互斥锁

1.NSLock:是Foundation框架中以对象形式暴露给开发者的一种锁

缺点:多次lock会造成线程死锁。

2.pthread_mutex

3.@synchronized:

实际项目中:AFNetworking中 isNetworkActivityOccurring属性的getter方法

- (BOOL)isNetworkActivityOccurring {

    @synchronized(self) {

        return self.activityCount > 0;

    }

}

自旋锁

1.OSSpinLock:

OSSpinLock lock = OS_SPINLOCK_INIT;

OSSpinLockLock(&lock);

...

OSSpinLockUnlock(&lock);

上面是OSSpinLock使用方式,编译会报警告,已经废弃了,OSSpinLock大家也已经不再用它了,因为它在某一些场景下已经不安全了,可以参考 YY大神的不再安全的 OSSpinLock,在Protocol Buffers项目中你可以看到这样的注释,大家已经用新的方案替换了。

// NOTE:OSSpinLock may seem like a good fit here but Apple engineers have// pointed out that they are vulnerable to live locking on iOS in cases of// priority inversion:// http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/// https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html

2.os_unfair_lock:

os_unfair_lock 是苹果官方推荐的替换OSSpinLock的方案,但是它在iOS10.0以上的系统才可以调用。

os_unfair_lock_t unfairLock;

unfairLock = &(OS_UNFAIR_LOCK_INIT);

os_unfair_lock_lock(unfairLock);

os_unfair_lock_unlock(unfairLock);

读写锁

上文有说到,读写锁又称共享-互斥锁,

pthread_rwlock:

//加读锁

pthread_rwlock_rdlock(&rwlock);

//解锁

pthread_rwlock_unlock(&rwlock);

//加写锁

pthread_rwlock_wrlock(&rwlock);

//解锁

pthread_rwlock_unlock(&rwlock);

递归锁

递归锁有一个特点,就是同一个线程可以加锁N次而不会引发死锁。

1.NSRecursiveLock:

NSRecursiveLock在YYKit中YYWebImageOperation.m中有用到:

_lock = [NSRecursiveLock new];

- (void)dealloc {

    [_lock lock];

    ...

    ...

    [_lock unlock];

}

2.pthread_mutex(recursive):

pthread_mutex锁也支持递归,只需要设置PTHREAD_MUTEX_RECURSIVE即可

pthread_mutex_t lock;

pthread_mutexattr_t attr;

pthread_mutexattr_init(&attr);

pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

pthread_mutex_init(&lock, &attr);

pthread_mutexattr_destroy(&attr);

pthread_mutex_lock(&lock);

pthread_mutex_unlock(&lock);

条件锁

1.NSCondition:

定义:

@interface NSCondition : NSObject <NSLocking> {

@private

    void *_priv;

}

- (void)wait;

- (BOOL)waitUntilDate:(NSDate *)limit;

- (void)signal;

- (void)broadcast;

遵循NSLocking协议,使用的时候同样是lock,unlock加解锁,wait是傻等,waitUntilDate:方法是等一会,都会阻塞掉线程,signal是唤起一个在等待的线程,broadcast是广播全部唤起。

NSCondition *lock = [[NSCondition alloc] init];

//Son 线程

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    [lock lock];

    while (No Money) {

        [lock wait];

    }

    NSLog(@"The money has been used up.");

    [lock unlock];

});

//Father线程

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    [lock lock];

    NSLog(@"Work hard to make money.");

    [lock signal];

    [lock unlock];

});

2.NSConditionLock:

定义:

@interface NSConditionLock : NSObject <NSLocking> {

@private

    void *_priv;

}

- (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER;

@property (readonly) NSInteger condition;

- (void)lockWhenCondition:(NSInteger)condition;

- (BOOL)tryLock;

- (BOOL)tryLockWhenCondition:(NSInteger)condition;

- (void)unlockWithCondition:(NSInteger)condition;

- (BOOL)lockBeforeDate:(NSDate *)limit;

- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;

很简单,方法很清晰,基本同上。

分布式锁

NSDistributedLock

NSDistributedLock是MAC开发中的跨进程的分布式锁,底层是用文件系统实现的互斥锁。NSDistributedLock没有实现NSLocking协议,所以没有lock方法,取而代之的是非阻塞的tryLock方法。

NSDistributedLock*lock = [[NSDistributedLockalloc] initWithPath:@"/Users/mac/Desktop/lock.lock"];while(![lock tryLock]) { sleep(1); }//do something[lock unlock];

当执行到do something时程序退出,程序再次启动之后tryLock就再也不能成功了,陷入死锁状态.其他应用也不能访问受保护的共享资源。在这种情况下,你可以使用breadLock方法来打破现存的锁以便你可以获取它。但是通常应该避免打破锁,除非你确定拥有进程已经死亡并不可能再释放该锁

信号量

dispatch_semaphore:

// 初始化dispatch_semaphore_tsemaphore_t= dispatch_semaphore_create(1);// 加锁dispatch_semaphore_wait(semaphore_t,DISPATCH_TIME_FOREVER);// 解锁dispatch_semaphore_signal(semaphore_t);/* 注: dispatch_semaphore 其他两个功能 1.还可以起到阻塞线程的作用. 2.可以实现定时器功能,这里不做过多介绍.

上一篇下一篇

猜你喜欢

热点阅读