为什么需要使用锁,当然熟悉多线程的你,自然不会对它觉得陌生。
那你在代码中是否很好的使用了锁的机制呢?你又知道几种实现锁的方法呢?
今天一起来探讨一下Objective-C中几种不同方式实现的锁,在这之前我们先构建一个测试用的类,假想它是我们的一个共享资源,method1与method2是互斥的,代码如下: @implementation TestObj - (void)method1
{
NSLog(@"%@",NSStringFromSelector(_cmd));
} - (void)method2
{
NSLog(@"%@",NSStringFromSelector(_cmd));
} @end
.使用NSLock实现的锁 //主线程中
TestObj *obj = [[TestObj alloc] init];
NSLock *lock = [[NSLock alloc] init]; //线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
[lock lock];
[obj method1];
sleep();
[lock unlock];
}); //线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
sleep();//以保证让线程2的代码后执行
[lock lock];
[obj method2];
[lock unlock];
});
看到打印的结果了吗,你会看到线程1锁住之后,线程2会一直等待走到线程1将锁置为unlock后,才会执行method2方法。
NSLock是Cocoa提供给我们最基本的锁对象,这也是我们经常所使用的,除lock和unlock方法外,NSLock还提供了tryLock和lockBeforeDate:两个方法,前一个方法会尝试加锁,如果锁不可用(已经被锁住),刚并不会阻塞线程,并返回NO。lockBeforeDate:方法会在所指定Date之前尝试加锁,如果在指定时间之前都不能加锁,则返回NO。
.使用synchronized关键字构建的锁
当然在Objective-C中你还可以用@synchronized指令快速的实现锁: //主线程中
TestObj *obj = [[TestObj alloc] init]; //线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
@synchronized(obj){
[obj method1];
sleep();
}
}); //线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
sleep();
@synchronized(obj){
[obj method2];
}
});
@synchronized指令使用的obj为该锁的唯一标识,只有当标识相同时,才为满足互斥,如果线程2中的@synchronized(obj)改为@synchronized(other),刚线程2就不会被阻塞,@synchronized指令实现锁的优点就是我们不需要在代码中显式的创建锁对象,便可以实现锁的机制,但作为一种预防措施,@synchronized块会隐式的添加一个异常处理例程来保护代码,该处理例程会在异常抛出的时候自动的释放互斥锁。所以如果不想让隐式的异常处理例程带来额外的开销,你可以考虑使用锁对象。
.使用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, ), ^{
pthread_mutex_lock(&mutex);
[obj method1];
sleep();
pthread_mutex_unlock(&mutex);
}); //线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
sleep();
pthread_mutex_lock(&mutex);
[obj method2];
pthread_mutex_unlock(&mutex);
});
pthread_mutex_t定义在pthread.h,所以记得#include <pthread.h>
.使用GCD来实现的”锁”
以上代码构建多线程我们就已经用到了GCD的dispatch_async方法,其实在GCD中也已经提供了一种信号机制,使用它我们也可以来构建一把”锁”(从本质意义上讲,信号量与锁是有区别,具体差异参加信号量与互斥锁之间的区别): //主线程中
TestObj *obj = [[TestObj alloc] init];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(); //线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[obj method1];
sleep();
dispatch_semaphore_signal(semaphore);
}); //线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
sleep();
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[obj method2];
dispatch_semaphore_signal(semaphore);
});
至于代码产生的效果当然和上一例是一模一样的,关于信号机制,熟悉C编程的你肯定也不会陌生的,关于GCD中更多关于dispatch_semaphore_t的信息,可以跳转到本博客的这一往篇文章:GCD介绍(三): Dispatch Sources
好了,以上就是我所列举了几种方式来实现锁,当然锁大多数情况下也是配合多线程一起使用的,关于多线程编程,我这儿就不赘述了。

转:http://www.tanhao.me/pieces/616.html

转 Objective-C中不同方式实现锁(一)的更多相关文章

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

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

  2. iOS中的几种锁的总结,三种开启多线程的方式(GCD、NSOperation、NSThread)

    学习内容 欢迎关注我的iOS学习总结--每天学一点iOS:https://github.com/practiceqian/one-day-one-iOS-summary OC中的几种锁 为什么要引入锁 ...

  3. iOS开发中多线程间关于锁的使用

    为什么需要使用锁,当然熟悉多线程的你,自然不会感到陌生. 那你在代码中是否很好的使用了锁的机制呢?你又知道几种实现锁的方法呢? main.m 1 int main(int argc, const ch ...

  4. [数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁

    注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的 ...

  5. 浅谈Objective—C中的面向对象特性

    Objective-C世界中的面向对象程序设计 面向对象称程序设计可能是现在最常用的程序设计模式.如何开发实际的程序是存在两个派系的-- 面向对象语言--在过去的几十年中,很多的面向对象语言被发明出来 ...

  6. Nginx学习之四-Nginx进程同步方式-自旋锁(spinlock)

    自旋锁简介 Nginx框架使用了三种消息传递方式:共享内存.套接字.信号. Nginx主要使用了三种同步方式:原子操作.信号量.文件锁. 基于原子操作,nginx实现了一个自旋锁.自旋锁是一种非睡眠锁 ...

  7. 【数据库】数据库的锁机制,MySQL中的行级锁,表级锁,页级锁

    转载:http://www.hollischuang.com/archives/914 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...

  8. C++线程中的几种锁

    线程之间的锁有:互斥锁.条件锁.自旋锁.读写锁.递归锁.一般而言,锁的功能越强大,性能就会越低. 1.互斥锁 互斥锁用于控制多个线程对他们之间共享资源互斥访问的一个信号量.也就是说是为了避免多个线程在 ...

  9. 【转】MySQL中的行级锁,表级锁,页级锁

    在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在数据库的锁机制中介绍过,在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引 ...

随机推荐

  1. SQL Case when 的使用方法 (转)

    Case具有两种格式.简单Case函数和Case搜索函数. --简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END ...

  2. Asp.net Vnext 调试源码

    概述 本文已经同步到<Asp.net Vnext 系列教程 >中] 如果想对 vnext深入了解,就目前为止太该只有调试源码了 实现 github上下载源码 选择对应的版本,版本错了是不行 ...

  3. 【51nod】1773 A国的贸易

    题解 FWT板子题 可以发现 \(dp[i][u] = \sum_{i = 0}^{N - 1} dp[i - 1][u xor (2^i)] + dp[i - 1][u]\) 然后如果把异或提出来可 ...

  4. LoadRunner11-遇到问题及解决办法(汇总)

    LoadRunner11-遇到问题及解决办法 1.LoadRunner超时错误:在录制Web服务器端,如果超过120秒服务器协议脚本回放时超时情况经常出现,产生错误的原因也有很多,解决的方法也不同.错 ...

  5. bzoj 1211: [HNOI2004]树的计数

    prufer的应用.. 详细见这篇博客:https://www.cnblogs.com/dirge/p/5503289.html import java.math.BigInteger; import ...

  6. PHP验证时有用的几段代码

    1.htmlspecialchars() htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体.预定义的字符是: & (和号) 成为 & " ( ...

  7. Object-c和Java中的代理

    代理模式的核心思想就是一个类想做一件事情(函数),但它不去亲自做(实现),而是通过委托别的类(代理类)来完成. 代理模式的优点: 1.可以实现传值,尤其是当一个对象无法直接获取到另一个对象的指针,又希 ...

  8. IDEA导入eclipse项目并部署运行完整步骤(转发)

    首先说明一下:idea里的project相当于eclipse里的workspace,而idea里的modules相当于eclipse里的project 1.File-->Import Proje ...

  9. 解释一下什么是servlet?

    Servlet是一种独立于平台和协议的服务器端的Java技术,可以用来生成动态的Web页面.与传统的CGI(计算机图形接口)和许多其他类似CGI技术相比,Servlet具有更好的可移植性.更强大的功能 ...

  10. 获取类的属性并排除特定属性(getType().GetProperties())

    当获取一个类型(class)的所有属性时,想排除指定属性,该如何操作? 比如:EF中一个实体类型UserEntity,通过反射获取这个类的属性时,想排除这个为映射的字段ID 使用以下方法即可! Pro ...