前言:OSSpinLock 性能真的很高?
@synchronize 性能真的很差?
OSSpinLock 的替代品 os_unfair_lock很高?
ibireme 的结论真的对吗?
1、主线程中测试代码:(测试环境:iPhone 7 iOS 13.4 MAC OS 10.15.4 xCode 11.4)
1.1、通过clock_gettime() 转换为微秒时间进行比较 ,通过在主线程中分别尝试10000次加锁,解锁操作 得出diff:
static uint32_t getCurrentTimeIntervalMicrosecond()
{
struct timespec time = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &time);
return (uint32_t)(time.tv_sec * 1000000 + time.tv_nsec / 1000);
}
- (void)spinLockTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
OSSpinLock spinLock = OS_SPINLOCK_INIT;
for (int i = 0; i < 10000;) {
OSSpinLockLock(&spinLock);
i++;
OSSpinLockUnlock(&spinLock);
}
NSLog(@"spinLock time:%d",getCurrentTimeIntervalMicrosecond() - before);
}
- (void)os_unfair_lock_test{
uint32_t before = getCurrentTimeIntervalMicrosecond();
os_unfair_lock osUnfairLock = OS_UNFAIR_LOCK_INIT;
for (int i = 0; i < 10000;) {
os_unfair_lock_lock(&osUnfairLock);
i++;
os_unfair_lock_unlock(&osUnfairLock);
}
NSLog(@"osUnfairLock time:%d",getCurrentTimeIntervalMicrosecond() - before);
}
- (void)os_unfair_lock_try_test{
uint32_t before = getCurrentTimeIntervalMicrosecond();
os_unfair_lock osUnfairLock = OS_UNFAIR_LOCK_INIT;
for (int i = 0; i < 10000;) {
if (os_unfair_lock_trylock(&osUnfairLock)) {
i++;
os_unfair_lock_unlock(&osUnfairLock);
}
}
NSLog(@"osUnfairTryLock time:%d",getCurrentTimeIntervalMicrosecond() - before);
}
- (void)pthread_mutex_normal_test{
uint32_t before = getCurrentTimeIntervalMicrosecond();
pthread_mutex_t normal_mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
pthread_mutex_init(&normal_mutex, &attr);
for (int i = 0; i < 10000;) {
pthread_mutex_lock(&normal_mutex);
i++;
pthread_mutex_unlock(&normal_mutex);
}
NSLog(@"PTHREAD_MUTEX_NORMALdiff time:%d",getCurrentTimeIntervalMicrosecond() - before);
pthread_mutexattr_destroy(&attr);
pthread_mutex_destroy(&normal_mutex);
}
- (void)pthread_mutex_recursive_test{
uint32_t before = getCurrentTimeIntervalMicrosecond();
pthread_mutex_t normal_mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&normal_mutex, &attr);
for (int i = 0; i < 10000;) {
pthread_mutex_lock(&normal_mutex);
i++;
pthread_mutex_unlock(&normal_mutex);
}
NSLog(@"PTHREAD_MUTEX_RECURSIVE diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
pthread_mutexattr_destroy(&attr);
pthread_mutex_destroy(&normal_mutex);
}
- (void)nslockTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSLock* lock = NSLock.new;
for (int i = 0; i < 10000;) {
[lock lock];
i++;
[lock unlock];
}
NSLog(@"NSLock diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
}
- (void)nsRecursiveLockTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSRecursiveLock* lock = NSRecursiveLock.new;
for (int i = 0; i < 10000;) {
[lock lock];
i++;
[lock unlock];
}
NSLog(@"NSRecursiveLock time:%d",getCurrentTimeIntervalMicrosecond() - before);
}
- (void)nslockConditionTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSCondition* lock = NSCondition.new;
for (int i = 0; i < 10000;) {
[lock lock];
i++;
[lock unlock];
}
NSLog(@"NSCondition diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
}
- (void)nslockConditionLockTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSConditionLock* lock = [[NSConditionLock alloc] initWithCondition:0];
for (int i = 0; i < 10000;) {
[lock lockWhenCondition:i];
i++;
[lock unlockWithCondition:i];
}
NSLog(@"NSConditionLock lock diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
}
- (void)synchronizeTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSNumber* number = @(100);
for (int i = 0; i < 10000;) {
@synchronized (number) {
i++;
}
}
NSLog(@"synchronize diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
}
1.2、测试结果:
2、异步在全局并发队列中执行10000次并打印结果,打印时间为毫秒:
2.1、测试代码:
//毫秒
static uint32_t getCurrentTimeIntervalMicrosecond()
{
struct timespec time = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &time);
return (uint32_t)(time.tv_sec * 1000 + time.tv_nsec / 1000000);
}
- (void)spinLockTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
static OSSpinLock spinLock = OS_SPINLOCK_INIT;
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
OSSpinLockLock(&spinLock);
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
OSSpinLockUnlock(&spinLock);
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result spinLockTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)os_unfair_lock_test{
uint32_t before = getCurrentTimeIntervalMicrosecond();
static os_unfair_lock osUnfairLock = OS_UNFAIR_LOCK_INIT;
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
os_unfair_lock_lock(&osUnfairLock);
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
os_unfair_lock_unlock(&osUnfairLock);
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result os_unfair_lock_test diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)os_unfair_lock_try_test{
uint32_t before = getCurrentTimeIntervalMicrosecond();
static os_unfair_lock osUnfairLock = OS_UNFAIR_LOCK_INIT;
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
if (os_unfair_lock_trylock(&osUnfairLock)) {
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
os_unfair_lock_unlock(&osUnfairLock);
}
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result os_unfair_lock_try_test diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)pthread_mutex_normal_test{
uint32_t before = getCurrentTimeIntervalMicrosecond();
static pthread_mutex_t normal_mutex;
static pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
pthread_mutex_init(&normal_mutex, &attr);
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
pthread_mutex_lock(&normal_mutex);
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
pthread_mutex_unlock(&normal_mutex);
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result pthread_mutex_normal_test diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)pthread_mutex_recursive_test{
uint32_t before = getCurrentTimeIntervalMicrosecond();
static pthread_mutex_t normal_mutex;
static pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&normal_mutex, &attr);
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
pthread_mutex_lock(&normal_mutex);
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
pthread_mutex_unlock(&normal_mutex);
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result pthread_mutex_recursive_test diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)nslockTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSLock* lock = NSLock.new;
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
[lock lock];
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
[lock unlock];
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result nslockTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)nsRecursiveLockTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSRecursiveLock* lock = NSRecursiveLock.new;
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
[lock lock];
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
[lock unlock];
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result nsRecursiveLockTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)nslockConditionTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSCondition* lock = NSCondition.new;
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
[lock lock];
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
[lock unlock];
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result nslockConditionTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)nslockConditionLockTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSConditionLock* lock = [[NSConditionLock alloc] initWithCondition:0];
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
[lock lockWhenCondition:i];
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
[lock unlockWithCondition:(i + 1)];
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result nslockConditionLockTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
- (void)synchronizeTest{
uint32_t before = getCurrentTimeIntervalMicrosecond();
NSNumber* number = @(100);
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10000;) {
dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
@synchronized(@(i)){
g_global_variable = i;
//NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
};
});
i++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"result synchronizeTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
});
}
2.2、惊奇发现调用顺序会影响结论,所以此结论不准:
2.3、每次启动单独调用某一个锁10000次: