#import <objc/runtime.h>
#import <objc/message.h>
#import <libkern/OSAtomic.h>
#import <pthread.h> #define ITERATIONS (1024*1024*32)
- (void)testLock
{
double then, now;
unsigned int i, count;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
OSSpinLock spinlock = OS_SPINLOCK_INIT; @autoreleasepool {
NSLock *lock = [NSLock new];
then = CFAbsoluteTimeGetCurrent();
for(i=0;i<ITERATIONS;++i)
{
[lock lock];
[lock unlock];
}
now = CFAbsoluteTimeGetCurrent();
printf("NSLock: %f sec\n", now-then); then = CFAbsoluteTimeGetCurrent();
for(i=0;i<ITERATIONS;++i)
{
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
now = CFAbsoluteTimeGetCurrent();
printf("pthread_mutex: %f sec\n", now-then); then = CFAbsoluteTimeGetCurrent();
for(i=0;i<ITERATIONS;++i)
{
OSSpinLockLock(&spinlock);
OSSpinLockUnlock(&spinlock);
}
now = CFAbsoluteTimeGetCurrent();
printf("OSSpinlock: %f sec\n", now-then); id obj = [NSObject new]; then = CFAbsoluteTimeGetCurrent();
for(i=0;i<ITERATIONS;++i)
{
@synchronized(obj)
{
}
}
now = CFAbsoluteTimeGetCurrent();
printf("@synchronized: %f sec\n", now-then);
} }

最近因为程序中频繁使用到了锁,不知道各种锁对性能的影响,今天稍作测试。顺便研究下里面的机制。

测试代码

测试原理:在一个线程中,对空代码段执行指定次数的加解锁。算出时间差。

测试代码请访问 Gist

测试结果

  • NSLock: 2.694002 sec
  • pthread_mutex: 1.761547 sec
  • OSSpinlock: 0.362136 sec
  • @synchronized: 6.849070 sec

可以看出来,用synchronized效率是最低的,而OSSpinlock效率高到无法直视。

详解synchronized OSSpinlock

@synchronized

创建给@synchronized指令的对象是一个用来区别保护块的唯一标示符。如果你在两个不同的线程里面执行上述方法,每次在一个线程传递了一个不同的对象给anObj参数,那么每次都将会拥有它的锁,并持续处理,中间不被其他线程阻塞。然而,如果你传递的是同一个对象,那么多个线程中的一个线程会首先获得该锁,而其他线程将会被阻塞直到第一个线程完成它的临界区。

作为一种预防措施,@synchronized块隐式的添加一个异常处理例程来保护代码。该处理例程会在异常抛出的时候自动的释放互斥锁。这意味着为了使用@synchronized指令,你必须在你的代码中启用异常处理。了如果你不想让隐式的异常处理例程带来额外的开销,你应该考虑使用锁的类。

OSSpinlock 官方描述

Spin locks are a simple, fast, thread-safe synchronization primitive that is suitable in situations

where contention is expected to be low. The spinlock operations use memory barriers to synchronize

access to shared memory protected by the lock. Preemption is possible while the lock is held.

结论

如果只是粗略的使用锁,不考虑性能问题可以使用synchronized。

如果对效率有较高的要求,还是采用OSSpinlock比较好。

因为Pthread的锁在也是用 OSSpinlock 实现的。OSSpinlock 的实现过程中,并没有进入系统kernel,使用OSSpinlock可以节省系统调用和上下文切换。


resources

@synchronized, NSLock, pthread, OSSpinLock showdown, done right

第四章 线程同步

Coneboy版权所有

转载注明出处

西安 iOS 开发

测试代码

对iOS锁的一些研究的更多相关文章

  1. iOS多线程的初步研究(六)

    iOS多线程的初步研究(六) iOS平台提供更高级的并发(异步)调用接口,让你可以集中精力去设计需完成的任务代码,避免去写与程序逻辑无关的线程生成.运行等管理代码.当然实质上是这些接口隐含生成线程和管 ...

  2. iOS多线程的初步研究3

    iOS多线程的初步研究(三) 弄清楚NSRunLoop确实需要花时间,这个类的概念和模式似乎是Apple的平台独有(iOS+MacOSX),很难彻底搞懂(iOS没开源,呜呜). 官网的解释是说run ...

  3. iOS多线程的初步研究1

    iOS多线程的初步研究(一) 对于多线程的开发,iOS系统提供了多种不同的接口,先谈谈iOS多线程最基础方面的使用.产生线程的方式姑且分两类,一类是显式调用,另一类是隐式调用. 一.显示调用的类为NS ...

  4. iOS多线程的初步研究

    iOS多线程的初步研究(四) 理解run loop后,才能彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的. 先看看NSTimer的两个常用方法: + (NST ...

  5. iOS多线程的初步研究(二)-- 锁

    谈到线程同步,一般指如何对线程间共享数据的同步读写,如何避免混乱的读写结果.一个基本的解决办法就是使用锁(LOCK). iOS提供多种同步锁的类和方法,这里介绍下基本用法. 1. NSLock:最基本 ...

  6. iOS多线程的初步研究(六)-- NSOperation

    iOS平台提供更高级的并发(异步)调用接口,让你可以集中精力去设计需完成的任务代码,避免去写与程序逻辑无关的线程生成.运行等管理代码.当然实质上是这些接口隐含生成线程和管理线程的运行,从而更加简洁地实 ...

  7. iOS 锁的常用方法

    锁的用法在iOS中有几种方法来解决多线程访问同一个内存地址的互斥同步问题: 方法一,@synchronized(id anObject),(最简单的方法)会自动对参数对象加锁,保证临界区内的代码线程安 ...

  8. c#中多线程同步Lock(锁)的研究以及跨线程UI的操作

    本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象.由于想更直观的显示结果,所以,在做demo的时候,就把多线程通过事件操作UI的代码也写了出来,留作备忘和分享吧. 其实多线程的同步,使用 ...

  9. iOS僵尸对象之研究

    Zombie Objects对象研究 一.Xcode 关闭ARC project -> Build settings  搜索 Automatic Reference Counting       ...

随机推荐

  1. 【原创】大数据基础之ETL vs ELT or DataWarehouse vs DataLake

    ETL ETL is an abbreviation of Extract, Transform and Load. In this process, an ETL tool extracts the ...

  2. centos7配置rsync+inotify数据实时共享

    关于centos7版本上面搭建rsync服务并且实现实时同步之前一直是在6版本上面搭建rsync服务,在7版本上面折腾了半天.此处总结下inotify下载地址:http://github.com/do ...

  3. Java 里 如何使用Base64,网上都是废物的说法

    百度搜索Java里如何使用Base64,结果很多文章都是让引用第三方Jar包,我靠我想了一下 他妈的Java里连这个都不提供,就直接忽略里那些废物的文章.继续搜索,算是找到答案: Java8以后 官方 ...

  4. 关于javascript的事件执行机制理解

    理解javascript事件执行机制 众所周知,js是一个单线程的语言,这意味着同一时间只能做一件事,但是我们又说js是异步的.首先,单线程并不是没有优点.作为浏览器脚本语言,JavaScript 的 ...

  5. navicat连接阿里云mysql

    1.服务器控制台在安全组配置3306端口 2.进入 /etc/ssh/sshd_config 在最下面 加入下面代码 KexAlgorithms diffie-hellman-group1-sha1, ...

  6. HTML 做圆形头像

    Click me <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  7. mysql服务脚本

    #!/bin/bash #*************************** #* copyleft huihui 2015-08-11 #**************************** ...

  8. Spring AOP学习笔记(1)-概念

    1.Aspect 横切在多个类的一个关注点,在Spring AOP中,aspect实现是一个规则的类或@Aspect标注的规则类.例如:事务管理 2.Join point 程序执行过程中的一个点,例如 ...

  9. unittest 报告——HTMLTestRunner/BSTestRunner+代码覆盖率

    1. HTMLTestRunner.py 代码(python3)如下: python2:  https://github.com/tungwaiyip/HTMLTestRunner "&qu ...

  10. python高级特征:列表生成式;generator, 迭代器。

    Python高级特性 列表生成式:不过一种语法糖 生成器:不过一个方法 迭代器: 列表生成式 Python内置的函数,来创建list. 简单的生成: >>> list(range(1 ...