为什么需要使用锁,当然熟悉多线程的你,自然不会对它觉得陌生。
那你在代码中是否很好的使用了锁的机制呢?你又知道几种实现锁的方法呢?
今天一起来探讨一下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. Ansible的基础元素和YAML介绍

    本节内容: YAML Ansible常用的数据类型 Ansible基础元素 一.YAML 1. YAML介绍 YAML是一个可读性高的用来表达资料序列的格式.YAML参考了其他多种语言,包括:XML. ...

  2. 微信小程序 跳一跳 外挂 C# winform源码

    昨天微信更新了,出现了一个小游戏“跳一跳”,玩了一下 赶紧还蛮有意思的 但纯粹是拼手感的,玩了好久,终于搞了个135分拿了个第一名,没想到过一会就被朋友刷下去了,最高的也就200来分把,于是就想着要是 ...

  3. HTML/CSS权值继承

    <style type="text/css">p{color:red;}.first{color:green;}/*因为权值高显示为绿色*/ span{color:pi ...

  4. 自定义Adapter为什么会重复多轮调用getView?——原来是ListView.onMeasure在作祟

    相信很多人在使用自定义Adapter的时候都遇到这样的问题: 假设Adapter数据源中只有30个Item,理论上每显示一个新的Item的时候就会调用一次getView,均显示一次的话是要调用getV ...

  5. Kafka(三)Kafka的高可用与生产消费过程解析

    一  Kafka HA设计解析 1.1 为何需要Replication 在Kafka在0.8以前的版本中,是没有Replication的,一旦某一个Broker宕机,则其上所有的Partition数据 ...

  6. 【LOJ】 #2033. 「SDOI2016」生成魔咒

    题解 就是字符集较大需要离散化和建边表的后缀自动机水题 每次会加入i个新的串,其中重复的就是i的父亲节点所在节点的长度,减掉即可 代码 #include <iostream> #inclu ...

  7. 微信公众号第三方平台生成自定义菜单提示 获取"access_token失败"

    在微信公众号第三方平台要生成自定义菜单时,程序反应很慢,最终提示"获取access_token失败"(之前程序无改动,使用时间已久),查了大半天,找不出原因. 排除.在微信公众号平 ...

  8. 查看锁信息(开启InnoDB监控)

    当前mysql版本:5.6.21 一.背景 在mysql处理死锁问题时,由于show engine innodb status输出来的死锁日志无任务事务上下文,并不能很好地诊断相关事务所持有的所有锁信 ...

  9. 论 异常处理机制中的return关键字

    Java中,执行try-catch-finally语句需要注意: 第一:return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂 ...

  10. MySQL 关于索引那点事

    索引 其实数据库中的数据是按页存放的其实索引也是按页存放的所以本质上索引也占硬盘空间(以最小的消耗,换取最大的利益) 索引是一种有效组合数据的方式!为快速查找到指定记录做铺垫 目的就是快速或者某个记录 ...