`

Objective-C中不同方式实现锁(1)

阅读更多

原文地址:http://www.tanhao.me/pieces/616.html/

 

为什么需要使用锁,当然熟悉多线程的你,自然不会对它觉得陌生。

那你在代码中是否很好的使用了锁的机制呢?你又知道几种实现锁的方法呢?

 

今天一起来探讨一下Objective-C中几种不同方式实现的锁,在这之前我们先构建一个测试用的类,假想它是我们的一个共享资源,method1与method2是互斥的,代码如下:

@implementation TestObj

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

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

@end

 1.使用NSLock实现的锁

//主线程中
TestObj *obj = [[TestObj alloc] init];
NSLock *lock = [[NSLock alloc] init];

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

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

 看到打印的结果了吗,你会看到线程1锁住之后,线程2会一直等待走到线程1将锁置为unlock后,才会执行method2方法。

NSLock是Cocoa提供给我们最基本的锁对象,这也是我们经常所使用的,除lock和unlock方法外,NSLock还提供了tryLock和lockBeforeDate:两个方法,前一个方法会尝试加锁,如果锁不可用(已经被锁住),刚并不会阻塞线程,并返回NO。lockBeforeDate:方法会在所指定Date之前尝试加锁,如果在指定时间之前都不能加锁,则返回NO。

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

当然在Objective-C中你还可以用@synchronized指令快速的实现锁:

//主线程中
TestObj *obj = [[TestObj alloc] init];

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

//线程2
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实现的锁

//主线程中
TestObj *obj = [[TestObj alloc] init];

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

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

//线程2
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定义在pthread.h,所以记得#include 

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

//主线程中
TestObj *obj = [[TestObj alloc] init];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

//线程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);
});

//线程2
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);
});

 至于代码产生的效果当然和上一例是一模一样的,关于信号机制,熟悉C编程的你肯定也不会陌生的,关于GCD中更多关于dispatch_semaphore_t的信息,可以跳转到本博客的这一往篇文章:GCD介绍(三): Dispatch Sources

好了,以上就是我所列举了几种方式来实现锁,当然锁大多数情况下也是配合多线程一起使用的,关于多线程编程,我这儿就不赘述了。

分享到:
评论

相关推荐

    Objective-C高级编程 iOS与OS X多线程和内存管理_Objective-C_ios_

    Objective-C提供了多种实现多线程的方式,如NSThread、NSOperationQueue、GCD(Grand Central Dispatch)等。书中会详细介绍这些机制的工作原理、使用方法以及它们之间的区别。例如,NSThread允许开发者创建并控制...

    objective-c面试大全

    3. **线程同步**:Objective-C中可以使用Mutex Lock(互斥锁)、NSCondition Lock、Message Passing等机制实现线程同步,以防止并发访问同一资源时产生数据竞争问题。 4. **函数`_memmove`**:这个函数模仿C语言...

    Objective-C代码风格指南

    Objective-C作为一种面向对象的编程语言,它结合了C语言的简洁性和Smalltalk风格的消息传递机制,是iOS和Mac OS X平台开发的重要语言。本指南中的内容涵盖了代码编写的各种细节,包括命名约定、代码布局、注释、类的...

    探索Objective-C的KVO:解锁动态属性观察的艺术

    3. **消息传递**:与传统的函数调用不同,Objective-C使用消息传递的方式实现对象之间的通信,这种机制让Objective-C与其他面向对象的语言有所区分。 4. **C语言兼容**:Objective-C与C语言高度兼容,意味着几乎所有...

    基于Objective-C实现创建手势密码+解锁手势密码+指纹验证功能+源码+源码解析(毕业设计&课程设计&项目开发)

    基于Objective-C实现创建手势密码+解锁手势密码+指纹验证功能+源码+源码解析,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于Objective-C实现创建手势密码+...

    PP软件授权平台 终端授权库IOS Objective-C调用示例代码 2019.03.13

    1. **导入库**:在Objective-C项目中,通过`#import`指令引入库头文件,以便使用库中的函数和类。 2. **初始化**:通常需要在应用启动时初始化授权库,这可能涉及到设置开发者ID、产品ID等参数。 3. **获取授权码*...

    Objective-C Runtime中的并发内存分配.pdf

    Objective-C Runtime机制是苹果Mac和iOS平台编程中的核心组成部分,它负责支持Objective-C语言运行时的各种特性,其中objc_msgSend函数是Runtime系统中最为关键的一个函数,它处理着所有的消息发送。本文将探讨...

    解锁Objective-C的KVC:深入Key-Value Coding的奥妙

    Objective-C是一种功能强大且灵活的面向对象编程语言,它在C语言基础上增加了面向对象的特性。自1980年代由Brad Cox和Tom Love设计以来,Objective-C经过苹果公司的采纳与改进,成为了macOS和iOS开发中的关键语言之...

    用户手势锁定和解锁视图_Objective-C_Ruby_下载.zip

    综上所述,这个压缩包中的内容可能是关于如何使用Objective-C实现一个自定义视图,该视图能够识别特定的手势以锁定或解锁视图状态。这不仅涉及到了手势识别,还涉及到视图控制和用户交互的处理,对于iOS开发者来说是...

    Objective-C面试题.pdf

    - **异常**:Objective-C支持C语言风格的错误处理,但在iOS开发中较少使用。 #### 二、中级技术题 1. **Category与Extension**: - **Category**:为现有类添加新方法的一种方式,不改变原始类定义。 - **...

    iOS-高仿支付宝手势解锁(九宫格)_Objective-C_下载.zip

    在Objective-C中实现这一功能,我们主要涉及以下几个步骤: 1. **界面设计**:使用UIKit框架创建一个自定义的UIView子类,用于显示九宫格。我们需要在视图上添加9个可点击的按钮,每个按钮代表一个点,可以通过...

    QQ和TouchID等手势锁屏,高仿QQ手势锁屏,手指解锁_Objective-C_C++_下载.zip

    在Objective-C中实现手势锁屏,开发者通常会用到以下几个关键知识点: 1. **UIPanGestureRecognizer**:这是iOS SDK中用于识别拖动手势的类,可以监听用户在屏幕上的滑动轨迹,从而判断是否与预设的手势匹配。 2. ...

    Objective-C 编程指南:从基础到实战,探索iOS开发的魅力-markdown文档教程.zip

    本教程不仅仅是一份简单的编程手册,它是一张精心绘制的地图,指引你从Objective-C的基础语法起航,一路航行至复杂功能的实现与优化。 你是否渴望构建出流畅、高效的iOS应用?是否希望深入理解内存管理,掌握自动...

    ios 内购代码 In App Rage objective c代码。最新版的已是swift版本。

    本教程主要针对iOS内购的实现,特别是使用Objective-C编写的代码,尽管最新的版本可能已经采用了Swift。 首先,我们需要理解内购的基本流程: 1. **设置App Store Connect**:在Apple的开发者中心,你需要在App ...

    856754611.zip_操作系统开发_Objective-C_

    1. 类(Class)和对象(Object):Objective-C是面向对象的语言,所有的功能都是通过类来实现的。 2. 消息传递:Objective-C使用消息传递来调用方法,类似于其他语言的函数调用。 3. 属性(Property)和访问器...

    objc4-750.zip

    10. **Block和GCD**:虽然Block和GCD主要由C语言实现,但在Objective-C中使用广泛。通过查看源码,我们可以了解Block的内存管理以及GCD的队列调度。 深入学习并理解objc4-750的源代码,对于Objective-C开发者来说是...

    IOS开发学习总结objectivec面向对象之——成员变量,模拟类变量,单例模式电脑资料.doc

    Objective-C 中的变量根据定义位置的不同,可以分为三大类:成员变量、局部变量和全局变量。成员变量是 Objective-C 中的实例变量,不支持真正的类变量。实例变量从该类的实例被创立开始起存在,直到系统完全销毁这...

    docobject-c面试题.doc

    `#import` 在Objective-C中用于包含其他头文件,与C语言中的 `#include` 类似,但会自动避免重复包含同一文件。 ### 12. MVC 设计模式 MVC(Model-View-Controller)是一种软件架构模式,将应用程序分为模型(数据...

    block使用方法

    这种Block与Objective-C中的Block有一些相似之处,但它们在语法和实现上有所不同。C语言中的Block允许开发者将代码块作为参数传递给函数,或者作为函数的返回值,这让C语言的函数式编程变得更加容易。 总结来说,...

Global site tag (gtag.js) - Google Analytics