ios面试知识复习Kevin的IOS开发专题

iOS中的锁机制

2016-05-23  本文已影响918人  不简单的风度

本文主要讨论OC中各种锁的使用。首先,创建一个用来测试的类。假设这个测试类是共享的资源,然后method1和method2是互斥的。
测试类:



#import "TestObject.h"

@implementation TestObject

- (void)method1
{
    NSLog(@"%@",NSStringFromSelector(_cmd));
}

- (void)method2
{
    NSLog(@"%@",NSStringFromSelector(_cmd));
}

@end

1.使用NSLock实现的锁

TestObject *obj = [[TestObject alloc] init];
NSLock *lock = [[NSLock alloc] init];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [lock lock];
    [obj method1];
    sleep(10);
    [lock unlock];
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);//以保证让线程2的代码后执行
    [lock lock];
    [obj method2];
    [lock unlock];
});

除lock和unlock方法外,NSLock还提供了tryLocklockBeforeDate:两个方法,前一个方法会尝试加锁,如果锁不可用(已经被锁住),刚并不会阻塞线程,并返回NO。lockBeforeDate:方法会在所指定Date之前尝试加锁,如果在指定时间之前都不能加锁,则返回NO。

2.使用synchronized关键字构建的锁


TestObject *obj = [[TestObject alloc] init];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    @synchronized(obj){
        [obj method1];
        sleep(10);
    }
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    @synchronized(obj){
        [obj method2];
    }
});

@synchronized指令使用的obj为该锁的唯一标识,只有当标识相同时,才为满足互斥,如果线程2中的@synchronized(obj)改为@synchronized(other),刚线程2就不会被阻塞,@synchronized指令实现锁的优点就是我们不需要在代码中显式的创建锁对象,便可以实现锁的机制,但作为一种预防措施,@synchronized块会隐式的添加一个异常处理例程来保护代码,该处理例程会在异常抛出的时候自动的释放互斥锁。所以如果不想让隐式的异常处理例程带来额外的开销,你可以考虑使用锁对象。

3.使用C语言的pthread_mutex_t实现的锁



TestObject *obj = [[TestObject alloc] init];

__block pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    pthread_mutex_lock(&mutex);
    [obj method1];
    sleep(5);
    pthread_mutex_unlock(&mutex);
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    pthread_mutex_lock(&mutex);
    [obj method2];
    pthread_mutex_unlock(&mutex);
});

由于pthread_mutex_t定义在C语言中的pthread.h,所以导入头文件要使用#include

4.使用GCD来实现的”锁”

以上代码构建多线程我们就已经用到了GCD的dispatch_async方法,其实在GCD中也已经提供了一种信号机制,使用它我们也可以来构建一把”锁”(从本质意义上讲,信号量是有区别,具体差异请自行查阅信号量与互斥锁之间的区别)


TestObject *obj = [[TestObject alloc] init];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [obj method1];
    sleep(10);
    dispatch_semaphore_signal(semaphore);
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [obj method2];
    dispatch_semaphore_signal(semaphore);
});

以上就是常用的锁机制,在网上查资料都说OSSpinLock 自旋锁效率是最高的,但是目前很多人都说自旋锁已经不再安全。如果算上OSSpinLock,各种锁的效率如下

OSSpinLock > pthread_mutex > NSLock > semaphore > @Sych

如果有有关于OSSpinLock是否安全的问题会及时更新。

上一篇下一篇

猜你喜欢

热点阅读