转载

同步-@synchronized, NSLock, pthread, OSSpinLock性能比较

起因是看到这篇 iOS中级面试题 ,说得比较中肯。很多知识点都接触过、也用过,但如果要答得好,还是得有系统的学习和总结。好记性不如烂笔头,所以就总结一下多线程中加锁的方法以及他们之间性能的比较。

原文地址: http://perpendiculo.us/2009/09/synchronized-nslock-pthread-osspinlock-showdown-done-right/

可能需要翻墙

稍微修改了原文的代码,因为文章是09年的,在Xcode7上面会报错。测试环境是非ARC

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
#import <libkern/OSAtomic.h>
#import <pthread.h>

#define ITERATIONS (1024*1024*32)

static unsigned long long disp=0, land=0;

typedef id(*_IMP) (id, SEL, ...);

int main(int argc, const char * argv[]) {


double then, now;
unsigned int i, count;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
OSSpinLock spinlock = OS_SPINLOCK_INIT;

NSAutoreleasePool *pool = [NSAutoreleasePool new];

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();
_IMP lockLock = (_IMP)[lock methodForSelector:@selector(lock)];
_IMP unlockLock = (_IMP)[lock methodForSelector:@selector(unlock)];
for(i=0;i<ITERATIONS;++i)
{
lockLock(lock,@selector(lock));
unlockLock(lock,@selector(unlock));

}
now = CFAbsoluteTimeGetCurrent();
printf("NSLock+IMP Cache: %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);
[pool release];


return 0;
}

耗时结果比较:

OSSpinlock < pthread_mutex < NSLock+IMP < NSLock < @synchronized

NSLock: 1.437285 sec
NSLock+IMP Cache: 1.359244 sec
pthread_mutex: 0.972748 sec
OSSpinlock: 0.311700 sec
@synchronized: 2.888747 sec

分析:

1、@synchronized

内部会创建一个异常捕获的handler和其他内部使用的锁。所以会消耗大量的时间

2、NSLock 和 NSLock+IMP

两个时间非常接近。他们是 pthread mutexes 封装的,但是创建对象的时候需要额外的开销。

3、pthread_mutex

底层的API,性能比较高。

4、OSSpinLock

自旋锁不进入内核,仅仅是重新加载。如果自旋锁占用的时间是极少的(通常是纳秒级别的)性能还是比较高的,减少了系统的直接调用和上下文的切换。

但是,如果有资源竞争的时候,会占用更多的cpu,耗电严重。这个时候,使用 pthread_mutex 可以避免电量的消耗,虽然耗时多一些。

原文  http://www.liuchendi.com/2016/01/13/iOS/33_Lock/
正文到此结束
Loading...