What will you do if you weren't afraid ?
概述我们在开发iOS应用期间,可能有时候就会遇到循环引用,或者内存分配状态等信息的问题,那么有没有办法可以在应用运行期间检测到了?答案是:当然有了!那就是开源的 FBMemoryProfiler ,由Facebook提供。使用起来也是非常的简单,下面我就讲解下
FBMemoryProfilerFBMemoryProfiler是一个在应用运行期间也可以浏览内存使用情况,专为iOS开发者设计的,基本包含FBAllocationTracker和FBRetainCycleDetector。
FBAllocationTracker是收集对象的信息,也支持生成和检测循环引用。
一。FBMemoryProfiler的安装与使用跟踪与现实内存使用情况
1.1 安装使用Carthage,那么你需要在项目的Cartfile文件里添加上代码如下:1github "facebook/FBMemoryProfiler"
FBMemoryProfiler需要在非debug(non-debug)模式下编译,所以你需要键入如下命令:1carthage update --configuration Debug
使用CocoaPods,那么需要你在Podfile文件里添加如下代码:1pod 'FBMemoryProfiler'
然后,在Terminal里cd到项目目录,最后键入pod install这个你完全可以在Debug模式下编译,这是有该编译标签控制的。
1.2 使用1.在main.m文件里添加如下代码,意味着开启FBAllocationTracker1234567891011#import <UIKit/UIKit.h>#import "AppDelegate.h"#import <FBAllocationTracker/FBAllocationTrackerManager.h>int main(int argc, char * argv[]) { [[FBAllocationTrackerManager sharedManager] startTrackingAllocations]; [[FBAllocationTrackerManager sharedManager] enableGenerations]; @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); }}
2.开启内存占用剖析检测功能123456#import <FBMemoryProfiler/FBMe
more
1.概念fishhook是一个非常牛的Mach-O二进制库,原因是因为它可以动态的重新绑定Mach-O符号,专门用于在iOS系统上(模拟器或者真机都可以)。
这个库的最大功能就是可以干涉系统函数,类似在Mac OS X上使用DYLD_INTERPOSE。
在Facebook,我们惊奇的发现使用fishhook可以勾住libSystem的函数调用,目的了?就是用于debugging(又叫做调试)或者tracing(又叫做追踪)。例如:对带有文件描述符的双重关闭问题进行稽核。原文是(auditing for double-close issues with file descriptors)。
2.用法使用的方法也是超简单,这里了,我们就拿打开(open())一个文件和关闭(close())一个文件来举例。我们把系统打开文件函数open重写一下(其实是叫做symbols rebinding),也对关闭文件函数close重写一下(它也叫作symbols rebinding)。代码如下:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758#import <dlfcn.h>//导入头文件#import "fishhook.h"//系统open函数的函数指针声明static int (*orig_open)(const char *, int, ...);//系统close函数的函数指针声明static int (*orig_close)(int);//对系统open函数重写(其实是符号重新绑定),但是我感觉就像是重写int my_open(const char *path, int oflag, ...){ va_list ap = {0}; mode_t mode = 0; if ((oflag & O_CREAT) != 0) { va_start(ap, oflag); mode = va_arg(ap, int); va_end(ap); printf("1.先调用my_open(),然后在调用系统的open() ('%s', %d, %d) \n", path, oflag, mode); return orig_open(path, oflag, mode); } else { printf("1.先调用my_open(
more
概述机器学习指的是机器通过统计学算法,对大量的历史数据进行学习从而生成经验模型,利用经验模型指导业务。
机器学习算法分类:
有监督学习(Supervised):针对打过标签的数据去预测新出现的数据。回归和分类本质上是类似的,所以很多的算法既可以用作分类,也可以用作回归。
回归(Regress),如果预测的内容是数值类型,就称为回归;
线性回归(Linear Regression),
分类(Classification),如果预测的内容是类别或者是离散的,就称为分类
支持向量机 SVM,
随机森林
神经网络
Gradient Boosting Tree
决策树
逻辑回归,虽然名字叫做回归,但它是分类算法
朴素贝叶斯
KNN
无监督学习(Unsupervised):没有打过标签的数据就是无监督学习
降维(Dimensionality Reduction)
就是把高维度的数据变成低维度,降维方法有PCA, LDA, SVD等
聚类(Clustering),就是把所有具有相同特质的数据归并在一起
K均值(K-Means),一种聚类算法
基于密度的聚类算法 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)
半监督学习:标签传播聚类
有一部分数据打过标签,对这一部分数据进行学习
Caffe简单介绍http://caffe.berkeleyvision.org
more
Convert trained models created with third-party machine learning tools to the Core ML model format.
OverviewIf your model is created and trained using a supported third-party machine learning tool, you can use Core ML Tools to convert it to the Core ML model format. There is Table as shown below, that lists the supported models and third-party tools.
NoteCore ML Tools is a Python package(coremltools), hosted at the Python Package Index(PyPI).
The table shows Models and third-party tools supported by Core ML Tools
Model Type
Supported Models
Supported Tools
—————————-
——————————————————————–
———————————-
Neural networks
Feedforward, convolutional, recurrent
Caffe v1, Keras 1.2.2+
—————————-
——————————————————————–
———————————-
Tree ensembles
Random forests, boosted trees, decision trees
scikit-learn 0.18, XGBoost 0.6
—————————-
——————————————————————–
———————————-
Support vector machines
Scalar regression, multiclass classification
scikit-learn 0.18, LIBSVM 3.22
—————————-
——————————————————————–
———————————-
Generalized linear models
Linear regression, logistic regression
scikit-learn 0.18
—————————-
——————————————————————–
———————————-
Feature engineeri
more
If you don’t know the basic use of Core ML, see this page , on the contrary, keep going our tutorial.
Use Vision with Core ML to perform image classification.
OverviewWith the Core ML framework, you can use a trained machine learning model to classify input data. The Vision framework works with Core ML to apply classification models to images, and to preprocess those images to make machine learning tasks easier and more reliable.
This tutorial I’m going to show you the open source MobileNet model, which identifies an image using 1000 classification categories as seen in the example screenshots below.
Figure - Official Test Case Download Sample Code
Figure - My Test Case
Now, we’ve seen it’s completely identified in official test case, but in my test case, half of them are failed to be identified. So I can sum this example code up,the trained model is unmatured.
But anyway, this is a good and easy step for us to going.
Start to my performanceCore ML automatically generates a Swift class which is MobileNet, that provides easy access to your ML model. To set up a Vision request using the model, create an instance of that class and use its model property to create a VNCoreMLReques
more
Core MLThis tutorial is based on Core ML which can be only running on iOS 11.Core ML allows you to integrate machine learning models into your app.I’ll show you Three Steps on getting started on CoreML basic use.
OverviewWith Core ML, you can integrate trained machine learning models into your app. As shown below.
So what is Trained Model?In fact, a Trained Model is the result of applying a machine learning algorithm to a set of training data. The model makes predictions based on new input data. For example, a model that’s been trained on a region’s historical house prices may be able to predict a house’s price when given the number of bedrooms and bathrooms.
Core ML is the foundation for domain-specific frameworks and funcitonality. Core ML supports Vision for image analysis, Foundation for natural language processing (for example, the NSLinguisticTagger class), and GameplayKit for evaluating learned decision trees. Core ML itself builds on top of low-level primitives like Accelerate and BNNS, as well as Metal Performance Shaders.
Core ML is optimized for on-device performance, which minimizes memory footprint and power consumption. Running strictly on the device ensures the pri
more
简介正确的认知自己的优点和缺点不仅仅是有助于你的职业(面试中必问),更重要的是生活。我之所以这么说,是因为每个人都有优点和缺点,人本身就不完美,但是我们会一致努力的让自己变得更好。
优点
喜欢学习和总结
对新鲜事物(我喜欢科技方面、技术方面)有追求
业余时间,会通过在线课程或者资料来提升自己的职业能力和未来的发展方向;
除此之外,也会学习一些生活方面的知识,比如:怎么运动来达到比较好的效果?作为一名程序员,每天趴在电脑面前,在业余时间或者周末有空的话,需要放松自己和适当锻炼。还有就是可以向父母学习学习做菜,这是比较重要的(会做饭菜的人(不管是男孩还是女孩,将来的生活一定很和谐,且幸福)
缺点作为一名程序员,大部分人会认为:古板,木讷,不善于表达;起初我也是这么认为自己的,但是,大家忘记了,程序员的自学能力很好,也很强;遇到问题一般自己会查资料,然后总结总结,最后解决问题。对于程序员的这种刻板印象也是同样的道理,所以我就看了一些文章、论坛和书籍,现在总结起来那些说的还是挺对了,比如:
对计算机的沟通很顺畅,对人际关系却表现的很不好,这只能说明程序员需要知道一些说话的技巧和策略,经过学习这些说话的技巧之后,一样可以达到与那位学心理学的同学的级别,甚至更好
对于逻辑思维的问题,可以认为程序员对代码的逻辑的理解肯定是相当不错的,但是与人交往时,有时候却发现对方不是听不懂,就是听不明白,其实有些时候,只是逻辑思考的不同,所以了,我买了一本书《简单的逻辑学》 我看完之后,总结有那么几点,但是都是大白话,没有术语:
1.说话时,考虑你说话的对象的理解程度和接受能力,使用合适词语来表达你的意思,尽量让对方能听懂和能接收。比如:在学习英语上,很多人学习英语时,和别人用英语交流时,尽说一些让人听不懂的概念或者词语,说明这个人只想证明自己的高大尚,与真正的交流毫无用处(我也犯过这样的问题,直到有一次我跟老外聊天时,他说:你的英语非常好,但是我是老外也听不懂呀😄)
2.关注细节,考虑到你说话的对象想从你这里得到什么样的答案,然后结合你自身的情况来表达
3.就是推理,任何事物都是有逻辑性或者规则的,只要经过细心推理,都是有规律的
4.找到实物的真实性
说话时,以前比较直接,可能话语会伤害到某人,但是以后经过学些一些技巧后,与人说话时,带点幽默感,可以起到非常大的作用,比如:缓解气氛,缩小人与人之间的距离。
最后,来说个 你认为你感到最失败的经验是什么以及对你的影响这个怎么说了,其实我觉得吧,就是当年在学校时,没把英语好好学,而导致后来在工作中需要花费很多额外的时间去补上😄
好了,以上就是我个人的部分经历,共勉。
more
很多时候,随着业务越来越好,系统所牵涉到的数据数量也是越来越多、越来越大,这时,许多系统的瓶颈就在数据的存储上了,所以我们就不得不考虑对数据库进行优化了。
从服务器的角度来讲,伸缩(scale)就是一种方式,它分为两种方法:
1.向上伸缩(scale up),它的意思是通过使用更好的硬件来提高系统的性能参数。
2.向外伸缩(scale out),它的意思是通过额外的硬件(如:服务器)来达到同样的效果。
读写分离读写分离的意思是,一个主数据库(master)负责写数据,一个从服务器(slave)的数据库负责读数据;master负责将写操作的数据同步到各个节点,读写分离来提供系统性能的有点:
物理服务器增加,机器处理能力提升,那硬件换性能
主从只负责各自的写和读,极大程度缓解了X锁和S锁争用
它们之间最大的问题就是同步,因为当一条数据写到主服务器后,从服务器如何同步?这几个主流数据库都是良好支持主从同步的:
MySQL Replication
MongoDB Master Slave Replication
Oracle Replication
SQL Server Replication
数据分片(data sharding)是将整体数据分开存放,如:服务器端,可以是将数据存放在多台服务器之间;客户端,可以是将数据库/数据表分开存放,以满足大数据量的需要。但是值得注意的是:本来是一张表或一个数据库的数据被分开存放了,那么对于select/insert/update/delete应该如何处理了?
策略如下:
1.根据取模,例如:先要对计算的key进行哈希计算,然后再对分开的表的数量或者设备进行取模运行,得到的结果是几,那么这条记录就放在编号为几的数据分区中
2.根据时间范围,例如:前50万条数据放在第一个分区中,第二个50万条数据放在第二个分区,依次类推
3.基于索引表:例如:新建立一个索引表,然后根据ID先去一个表内找到它所在的分区,然后再去目标分区进行查找
数据分区虽然好处多多,尤其是对系统的性能(performance)和伸缩性(scalability),但是同时也带来是开发的复杂度。
那SQLite如何优化了?FMDB是基于SQLite封装的。早期的FMDB是不支持并发的,但是后来的版本中,FMDB已经解决了在并发问题。SQLite共识:
四种锁:
共享锁(shared lock)
预留锁(reserved lock)
未决锁(pending lock)
排他锁(exclusive lock)
SQLite读操作(如:select),可以并发的读取数据库,如果有一个读存在,那么就不允许写
SQLite写操作(如:insert/update/delete),
1.它首先会申请一个预留锁(reserved lock),在启用预留锁后,如
more
移除CSDN各种广告 - Safari浏览器专用插件故事背景:受够了CSDN的各种垃圾广告,还满天飞。。。每次查资料时,总是郁闷的看到了左下角,右下角的广告,忍无可忍之日,今天,我就专门写了个工具,其实是Safari插件,干掉 CSDN.com 和 CSDN.net上的各种页面的广告。如果你也和我一样烦透了CSDN的广告,那就装上我写的这个插件吧。超级简单的哦~~~由于我把这个小插件放到了Firebase的仓库,所以下载时,需要你的网络可以连接Google,如果你的网络不能连接google,请给我发邮件或者本站的右边栏的联系方式联系我,我会给你直接发送插件
方案1
1.该下载要求你的网络可以连接上google, 下载插件
2.下载完后,解压该下载文件,然后建议是把这个解压完的整个文件夹拷贝到你的 ~/Documents目录
3.打开Safari -> Developer -> Show Extension Builder -> 左下角 Add Extension -> 添加 ~/Documents/EliminateCSDNAds.safariextension -> 点击右上角 install按钮
4.然后打开Safari的Preferences -> Extensions ,你就可以看到刚才安装的文件了
5.快去打开 www.csdn.net 试试吧,广告都没了。。。O(∩_∩)O哈哈~
注意:
1.如果你在第三步时,找不到Developer菜单项的话,记得如下图开启
2.如果你在第三步时,找不到添加插件的按钮,如下图
如果你有更好的意见,欢迎 mailto: victorzhangq@gmail.com ,我会尽快处理
方案2
1.下载此文件需要你的网络能连接google 立马下载”移除CSDN广告”的Safari插件
2.下载完后需要解压
3.解压完后,双击SafariExtensionsPro.app文件,然后打开Safari,在左上角选择Preferences,然后选择Extensions,然后你就会看到插件移除CSDN广告。
4.勾选上移除CSDN广告后,你会在浏览器中间偏左看到如图所示,它表示插件已经生效
5.最后你就可以去访问www.csdn.net时,你就再也看不到各种悬浮广告,解决了你的心头之恨吧!!😄
注意
如果在第三步时,没有看到如图所示的插件,那么可以尝试关闭Safari浏览器,在打开,一般第二次或者第三次打开就能显示出来了
如果你有更好的建议,或者说,你还想屏蔽哪些网站的广告,请邮件我,我会抽空添加的😄
DIY一个插件
more
目录
1.介绍
2.下载与安装
3.实例说明(Python代码)
4.实例说明(Objective-C代码)
5.文件.proto的解释
1.介绍Protocol Buffer,简单来说,就是一种数据交换格式,就像JSON和XML作用一样,只不过Protocol Buffer是Google开源的一套二进制流网络传输协议,它独立于语言,独立于平台;而且它的性能、速度等非常优越于JSON和XML。google 提供了多种语言的实现:objective-c, swift,java、c#、c++、Go 和Python等,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
对于XML来说,Protocol Buffers有太多优点了,尤其是针对序列化结构数据。优点:
更简单
小到3-10倍
快到20-100倍
相当少的歧义
文档型协议
T-L-V的数据存储方式 Tag-Length-Value
注意protobuf目前有两个版本proto2和proto3。这两个版本的语法并不是完全兼容的,所以为了避免使用时的麻烦,请仔细阅读proto2和proto3的语法。
2.下载与安装我的环境:macOS Sierra Version 10.12.6
1.下载最新版本的ProtoBuff (我下载的是v3.4.1)。下载完后,解压压缩包。注意:解压后里面的objectivec目录是给iOS和macOS专用
2.然后依次键入以下命令进行安装,以下的每个命令都可能或占用几分钟时间,请耐心等待下12345678$> cd protobuf-3.4.1/$> ./configure$> make$> make check$> make install// 当输入此步骤时,如果正常输出版本号信息,就表示安装正确了$> protoc --version
Python的使用命令Python教程编译一个.proto文件,命令如下:123//$SRC_DIR 为源文件目录//$DST_DIR 为目标文件目录protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/addressbook.proto
然后,你就会看到后缀为:_pb2.py的文件在你指定的目录下。
Objective-C的使用命令Objective-C教程编译一个.proto文件,命令如下:123//$SRC_DIR 为源文件目录//$DST_DIR 为目标文件目录protoc --proto_path=$SRC_DIR
more
简介优先级反转 英文名叫做 Priority Inversion,一句话概括它的意思:低优先级任务要比高优先级任务先执行。
先明白一些背景知识
1.操作系统是多任务的
2.任务之间谁都可以得到执行,是通过任务调度来完成
3.任务调度有多种算法,常见的有:
罗宾环调度算法:Round-robin scheduling algorithm
基于优先级的调度算法:Priority-controlled scheduling algorithm
4.一般操作系统用的就是优先级调度算法,根据优先级别高低去调度,也就是优先级高的先执行,优先级低的后执行;
任务调度器,总是先去激活所有任务中优先级别最高的任务,且该任务处于就绪状态,然后让它执行
任务有多种状态:就绪,挂起,执行等;常见的如:需要某种资源时被别的任务占用了,那么当前任务就不得不挂起,先让被占用资源的任务执行
5.任务一般被称为:进程,或者粒度更小的线程
详细解释下为什么假设有以下条件
1.任务A (低优先级)
2.任务B (中优先级)
3.任务C (高优先级)
4.资源
步骤
1.已知任务调度器总是去激活所有任务中优先级最高的,且处于就绪状态的任务,去执行;但是当某个最高优先级的任务A,由于其所需要的某个资源被低优先级任务C所占用,而且还没有释放,那么高优先级任务A就被阻塞了。
2.按照调度规则:
此高优先级任务A,必须等到低优先级任务C把自己占用的资源释放后,才能继续运行;
但是要等到低优先级任务C释放其所占用的资源的话,则很明显,必须要让低优先级任务C 先去执行,然后等低优先级任务C执行完毕并释放资源后,高优先级任务A就能得到的那个资源了;
但是,问题就是:在高优先级任务A执行的这段时间内,某个中优先级任务B已经处于就绪状态了,所以当高优先级任务A,由于所需要的资源被占用而挂起,然后中优先级任务B,由于比低优先级任务C的优先级高,所以被调度执行,然后中优先级任务B就一直执行,知道结束。
3.这种情况就是:一个中等优先级任务B,却比一个高更优先级的任务A 先执行,这就叫做优先级反转
问题:本来应该是优先级最高的任务A先执行的,结果却变成了,比高优先级任务A要低一些的中优先级任务B先执行了。优先级反转如名字一样,就是他们的优先级别互换了一下(反转了一下)。
有的朋友会问了,反转就反转了呗😄,有什么大不了的,程序还不是照样运行吗?
优先级反转的有和危害实话说,当我刚学习计算机的时候,对计算机的概念都真的只是个概念,背后的技术和逻辑学的也是云里云雾的,而慢慢的成长,就会发现以前不理解的知识,现在看起来很重要很重要,而且也容易理解些了。
对于实时系统,最重要的指标就是:确保任务执行时间是可预测的,即涉及到最后时间点等比如:要确保,某个时刻在执行某个任务,都不能超过某个时间等
more
概念RunLoop是iOS和OS X开发中非常基础的知识,通过RunLoop可以实现自动释放池,延迟回调,触摸事件,屏幕刷新等功能。
一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,通常的代码如下:1234567function loop() { initialize(); do { var message = get_next_message(); process_message(message); } while (message != quit);}
这种模型通常被称作 Event Loop。 Event Loop 在很多系统和框架都有实现,比如Node.js的事件处理,比如Windows程序消息循环,再比如iOS/OS X里的RunLoop.实现这种模型的关键点在于:如何管理事件/消息,如何让线程在没有处理消息时休眠以避免资源占用、在有消息来到时立刻被唤醒。
所以 RunLoop 实际上就是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一个入口函数来执行上面的 Event Loop 的逻辑。线程执行了这个函数后,就会一直处于这个函数内部 “接收消息 -> 等待 -> 处理” 的循环中,知道这个循环结束(比如传入quit的消息),函数返回。
在iOS/OS X系统中,提供了两个这样的对象:NSRunLoop和CFRunLoopRef。CFRunLoopRef是在CoreFoundation框内的,提供了纯C函数的API,代码是开源的,所有这些API都是线程安全的。NSRunLoop是基于CFRunLoopRef的封装,提供了面向对象的API,但是这些API不是线程安全的。
Swift开源后,苹果又维护了一个跨平台的CoreFoundation版本:https://github.com/apple/swift-corelibs-foundation/ 这个版本的源码可能和现有的iOS系统中的实现略有不同,但是更容易编译,因为它已经适配了 Linux/Windows
RunLoop对外的接口在CoreFoundation里面关于RunLoop有5个类
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
其中 CFRunLoopModeRef 类并没有对外暴露,只是通过 CFRunLoopRef 的接口进行了封装。他们的关系如下:
一个RunLoop包含若干个Mode
每个Mode包含若干个Source/Timer/Observer
每次调用RunLo
more
简介NSThread多线程编程,超级简单,NSthread是基于pthread_t封装的,所以基本上在使用方面pthread_t和NSThread差不多
线程的生命周期,五种状态
1.新建(new Thread),就是实例化了一个线程对象 在iOS中,self.alwasyThread = [[NSThread alloc] initWithTarget:self selector:@selector(alwaysRun) object:nil];
2.就绪(runnable),就是线程在就绪队列中等待CPU分配时间片,一般是start方法 在iOS中,[self.alwasyThread start];
3.运行(running),就是线程已经获得CPU资源并且马上执行任务,一般是run方法 在iOS中,start方法就表示进入就绪状态,并且获得CPU资源后进入运行状态
4.死亡(dead),就是线程执行完任务,或者被其他线程杀死,这时就不能再进入就绪状态,重新运行。调用stop方法终止线程 在iOS中,[NSThread exit];
5.阻塞(blocked),就是某种原因导致正在运行的线程暂停自己,让出CPU,那么自己就进入了阻塞状态(suspend),阻塞状态可以调用resume恢复 在iOS中,sleep(3);,[NSThread sleepForTimeInterval:3.0f];,[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0]];
我们分三步说下吧
1.创建子线程第一种方式12345678- (void)nsthread_test { NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; [thread start];}- (void)run { NSLog(@"NSThread子线程 %@", [NSThread currentThread]);}
输出为:12017-10-16 test[25785:1117888] NSThread子线程 <NSThread: 0x604000270200>{number = 3, name = (null)}
第二种方式,仅限iOS 10及以上版本可用1234NSThread *thread = [[NSThread alloc] initWithBlock:^{ NSLog(@"NSThread子线程 %@", [NSTh
more
简介在多线程编程中,并发会使一段代码在同一段时间内线程之间互相争抢资源(资源共享)而产生数据的不一致性,为了解决这个问题,就引入了锁。锁的类型有多种,在iOS中,有如下:
1.OSSpinLock 自旋锁
2.dispatch_semaphore GCD信号量实现加锁
3.pthread_mutex 互斥锁
4.NSLock 互斥锁
5.NSCondition 信号锁
6.pthread_mutex(recursive) 递归互斥锁
7.NSRecursiveLock 递归锁
8.NSConditionLock 条件锁
9.@synchronized 互斥锁
在看本篇文章前,请先了解GCD和NSOperation, 如果你已熟知,请继续往下看。
我们先来看下iOS中全部的锁,以及它们的效率
这个简单的性能测试是在iPhone 6, iOS 9上跑的,测试者在这篇文章该结果显示的,横向柱状条最短的为性能最佳和最高;可知,OSSpinLock最佳,但是OSSpinLock被发现bug,Apple工程师透露了这个自旋锁有问题,暂时停用了,查看这里虽然OSSpinLock(自旋锁)有问题,但是我们还是看到了pthread_mutex和dispatch_semaphore性能排行仍是很高,而且苹果在新系统中也已经优化了这两个锁的性能,所以我们在开发时也可以使用它们啦。
下面来一一介绍它们的使用
1.dispatch_semaphore GCD信号量实现加锁GCD中提供了一种信号机制,也是为了解决资源抢占问题的,支持信号通知和信号等待。
1.每当发送一个信号时,则信号量加1
2.每当发送一个等待信号时,则信号量减1
3.如果信号量为0,则信号会处于等待状态,直到信号量大于0时就开始执行
12345678910111213141516171819202122232425262728293031- (void)example { //假设一共电影票3张票 self.movieTickets = 3; //创建信号量 dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); //添加任务1 dispatch_async(dispatch_get_global_queue(0, 0), ^{ [self buyTicketWithCounts:2 taskName:@"任务1" semaphore:semaphore]; }); //添加任务2 dispatch_async(dispatch_get_global_queu
more