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

12345678910111213
@implementation TestObj

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

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

@end

1.使用NSLock实现的锁

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

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

//线程2dispatch_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指令快速的实现锁:

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

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

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

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

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

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

//线程2dispatch_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中也已经提供了一种信号机制,使用它我们也可以来构建一把”锁”(从本质意义上讲,信号量与锁是有区别,具体差异参加信号量与互斥锁之间的区别):

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

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

//线程2dispatch_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

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

转载于:https://www.cnblogs.com/fanjing/p/4543611.html

oc中不同方式实现锁相关推荐

  1. iOS开发中自旋和互斥锁的理解以及所有锁的性能比较

    补充: 可以看到除了 OSSpinLock 外,dispatch_semaphore 和 pthread_mutex 性能是最高的.苹果在新系统中已经优化了 pthread_mutex 的性能,所以它 ...

  2. OC中的NSArray和NSMutableArray、NSDictionary和NSMutableDictionary用法

    一:NSArray 和NSMutableArray 1: NSArray:不可变数组 NSArray是OC中使用的数组,只能用来存放OC对象,不能存放非OC对象如基本数据类型 它使不可变的,一旦初始化 ...

  3. iOS开发几年了,你清楚OC中的这些东西么!!!?

    iOS开发几年了,你清楚OC中的这些东西么!!!? 前言 几年前笔者是使用Objective-C进行iOS开发, 不过在两年前Apple发布swift的时候,就开始了swift的学习, 在swift1 ...

  4. 图解Java中那18 把锁

    乐观锁和悲观锁 独占锁和共享锁 互斥锁和读写锁 公平锁和非公平锁 可重入锁 自旋锁 分段锁 锁升级(无锁|偏向锁|轻量级锁|重量级锁) 锁优化技术(锁粗化.锁消除) 乐观锁和悲观锁 悲观锁 悲观锁对应 ...

  5. 24张图带你彻底理解Java中的21种锁

    本篇主要内容如下: 本篇主要内容 本篇文章已收纳到我的Java在线文档. Github 我的SpringCloud实战项目持续更新中 帮你总结好的锁: 序号 锁名称 应用 1 乐观锁 CAS 2 悲观 ...

  6. java中怎么判断一段代码时线程安全还是非线程安全_24张图带你彻底理解Java中的21种锁...

    (给ImportNew加星标,提高Java技能) 转自:悟空聊架 本篇主要内容如下: 本篇文章已收纳到我的 Java 在线文档. Github.我的 SpringCloud 实战项目持续更新中. 帮你 ...

  7. OC中的基本容器和基本数据类型

    基本数据类型 NSRange 是一个结构体,里面有两个数据成员数据类型都为NSUInteger 就是c语言中的无符号整形,一个是location表示集合的起始地址,另外一个变量是length表示从起始 ...

  8. 图解Java中的18 把锁!

    乐观锁和悲观锁 独占锁和共享锁 互斥锁和读写锁 公平锁和非公平锁 可重入锁 自旋锁 分段锁 锁升级(无锁|偏向锁|轻量级锁|重量级锁) 锁优化技术(锁粗化.锁消除) 乐观锁和悲观锁 悲观锁 悲观锁对应 ...

  9. 多图带你彻底理解Java中的21种锁!

    作者 | 悟空聊架构 来源 | 悟空聊架构(ID:PassJava666) 本篇主要内容如下: 本篇主要内容 本篇文章已收纳到我的Java在线文档. Github 我的SpringCloud实战项目持 ...

最新文章

  1. android 设置PopupWindow的显示大小
  2. uniny 物体运动到一个点停止_人教版高中英语必修五Unit 5 单词详解
  3. 100*100的 canvas 占多少内存?
  4. 爬虫-36kr-接口分析-191016
  5. 实训项目四 powerpoint 综合应用_【深化改革结硕果】新疆番茄综合精深加工关键技术及产业化应用项目取得重大突破...
  6. angularjs揭秘
  7. VC++ 结束线程 AfxBeginThread AfxEndThread
  8. 手机号识别轻松对着号码扫一扫就录入了
  9. jsp员工管理系统mysql_基于JSP的企业员工信息管理系统的设计(MySQL)
  10. [设计模式]解释器模式
  11. 《kiss the rain》与追求完美的矛盾个体
  12. 远程桌面提示 “终端服务器超出了最大允许连接数” 的解决方法
  13. 云计算、大数据和人工智能之间的关系
  14. 基于MC9S12G使用编码器(控制)输出PWM
  15. python用正则写银行系统_python使用正则表达式(Regular Expression)方法超详细
  16. Springboot启动流程分析(四):完成启动流程
  17. Word怎么删除空白页操作方法 Word删除空白页的办法详解oldtimeblog
  18. Android使用exchange日历,使用Exchange服务实现跨平台(PC+Web + 移动端)日历的日程管理...
  19. 补码加法器中低位进位信息是什么?
  20. vue+jQuery

热门文章

  1. 育人优化计算机试题,优化公寓育人氛围,增强学生自律意识——数学系、计算机科学系开展PPT制作和个人简历制作大赛...
  2. 年度审计报告是什么意思?年度报表审计的基本流程
  3. 不要再来问我小学、初中毕业想出去学习编程找到工作的问题了,你要做就去做,结果自己扛着就行了!
  4. (九)自签证书和DNS
  5. 幸福人生讲座下载地址
  6. css3-文字外发光效果2-文字描边
  7. question2answer之旅
  8. 供应商的绩效考核主要考虑哪些方面
  9. 对话极客修CEO吴玮:线上线下融合将催生旗舰型维修服务平台
  10. 查询出百世快递的物流,快速筛选出已签收的单号