`

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

阅读更多

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

 

在上一文中,我们已经讨论过用Objective-C锁几种实现(跳转地址),也用代码实际的演示了如何通过构建一个互斥锁来实现多线程的资源共享及线程安全,今天我们继续讨论锁的一些高级用法。

1.NSRecursiveLock递归锁

 

平时我们在代码中使用锁的时候,最容易犯的一个错误就是造成死锁,而容易造成死锁的一种情形就是在递归或循环中,如下代码:

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

//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    static void(^TestMethod)(int);
    TestMethod = ^(int value)
    {
        [theLock lock];
        if (value > 0)
        {
            [obj method1];
            sleep(5);
            TestMethod(value-1);
        }
        [theLock unlock];
    };

    TestMethod(5);
});

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

以上的代码中,就是一种典型的死锁情况,因为在线程1中的递归block中,锁会被多次的lock,所以自己也被阻塞了,由于以上的代码非常的简短,所以很容易能识别死锁,但在较为复杂的代码中,就不那么容易发现了,那么如何在递归或循环中正确的使用锁呢?此处的theLock如果换用NSRecursiveLock对象,问题便得到解决了,NSRecursiveLock类定义的锁可以在同一线程多次lock,而不会造成死锁。递归锁会跟踪它被多少次lock。每次成功的lock都必须平衡调用unlock操作。只有所有的锁住和解锁操作都平衡的时候,锁才真正被释放给其他线程获得。

2.NSConditionLock条件锁

当我们在使用多线程的时候,有时一把只会lock和unlock的锁未必就能完全满足我们的使用。因为普通的锁只能关心锁与不锁,而不在乎用什么钥匙才能开锁,而我们在处理资源共享的时候,多数情况是只有满足一定条件的情况下才能打开这把锁:

//主线程中
NSConditionLock *theLock = [[NSConditionLock alloc] init];

//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    for (int i=0;i<=2;i++)
    {
        [theLock lock];
        NSLog(@"thread1:%d",i);
        sleep(2);
        [theLock unlockWithCondition:i];
    }
});

//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [theLock lockWhenCondition:2];
    NSLog(@"thread2");
    [theLock unlock];
});

  在线程1中的加锁使用了lock,所以是不需要条件的,所以顺利的就锁住了,但在unlock的使用了一个整型的条件,它可以开启其它线程中正在等待这把钥匙的临界地,而线程2则需要一把被标识为2的钥匙,所以当线程1循环到最后一次的时候,才最终打开了线程2中的阻塞。但即便如此,NSConditionLock也跟其它的锁一样,是需要lock与unlock对应的,只是lock,lockWhenCondition:与unlock,unlockWithCondition:是可以随意组合的,当然这是与你的需求相关的。

3.NSDistributedLock分布式锁

以上所有的锁都是在解决多线程之间的冲突,但如果遇上多个进程或多个程序之间需要构建互斥的情景该怎么办呢?这个时候我们就需要使用到NSDistributedLock了,从它的类名就知道这是一个分布式的Lock,NSDistributedLock的实现是通过文件系统的,所以使用它才可以有效的实现不同进程之间的互斥,但NSDistributedLock并非继承于NSLock,它没有lock方法,它只实现了tryLock,unlock,breakLock,所以如果需要lock的话,你就必须自己实现一个tryLock的轮询,下面通过代码简单的演示一下吧:

程序A:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    lock = [[NSDistributedLock alloc] initWithPath:@"/Users/mac/Desktop/earning__"];
    [lock breakLock];
    [lock tryLock];
    sleep(10);
    [lock unlock];
    NSLog(@"appA: OK");
});

 程序B:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        lock = [[NSDistributedLock alloc] initWithPath:@"/Users/mac/Desktop/earning__"];

        while (![lock tryLock]) {
            NSLog(@"appB: waiting");
            sleep(1);
        }
        [lock unlock];
        NSLog(@"appB: OK");
    });

 先运行程序A,然后立即运行程序B,根据打印你可以清楚的发现,当程序A刚运行的时候,程序B一直处于等待中,当大概10秒过后,程序B便打印出了appB:OK的输出,以上便实现了两上不同程序之间的互斥。/Users/mac/Desktop/earning__是一个文件或文件夹的地址,如果该文件或文件夹不存在,那么在tryLock返回YES时,会自动创建该文件/文件夹。在结束的时候该文件/文件夹会被清除,所以在选择的该路径的时候,应该选择一个不存在的路径,以防止误删了文件。

分享到:
评论

相关推荐

    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

    Objective-C是C语言的超集,添加了面向对象的特性,广泛用于苹果的生态系统中,包括iOS和Mac OS X应用开发。 此示例代码的目的是帮助开发者理解如何在自己的应用中集成PP软件授权平台。开发者需要了解如何在Xcode...

    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版本。

    2. **集成StoreKit**:在iOS应用中,通过导入StoreKit框架来实现内购功能。StoreKit提供了一系列的API用于查询商品、处理交易以及验证购买信息。 3. **查询商品**:使用`SKProductsRequest`类获取应用内购买项目的...

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

    Objective-C的语法与C语言兼容,同时增加了Smalltalk式的消息传递机制,这使得它非常适合构建动态和灵活的用户界面。 这个"856754611.zip"压缩包中包含的"ABPadLockScreenDemo"和"ABLockScreen"可能是一个iOS应用的...

    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