zoukankan      html  css  js  c++  java
  • IOS 锁

    参考自:http://perpendiculo.us/2009/09/synchronized-nslock-pthread-osspinlock-showdown-done-right/,尊重原创!

    苹果多线程 锁的文档 https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html

    常见的几种锁有: synchronized 、 NSLock、  pthread_mutex 、OSSpinLock

    另外还有:NSRecursiveLock、NSConditionLock、NSDistributedLock 等

    一、用法如下:

     1 /*
     2  功能:一个售票程序
     3  后台共有票数,窗口数
     4  
     5  结构:窗口之间并行  每个窗口内部串行
     6  */
     7 #import "SaleViewController.h"
     8 #import "pthread/pthread.h"
     9 #import "libkern/OSAtomic.h"
    10 
    11 
    12 @interface SaleViewController ()
    13 {
    14     long long  _ticketsCount;
    15     int salesGirls;
    16     NSLock *_myLock;
    17     OSSpinLock _spinLock;
    18 }
    19 @end
    20 
    21 static pthread_mutex_t sDefaultMutex = PTHREAD_MUTEX_INITIALIZER;
    22 
    23 @implementation SaleViewController
    24 
    25 - (id)init
    26 {
    27     if(self = [super init]){
    28         _ticketsCount = 30;
    29         salesGirls = 6;
    30         _myLock = [NSLock new];
    31         _spinLock = OS_SPINLOCK_INIT;
    32     }
    33     return self;
    34 }
    35 
    36 - (void)viewDidLoad {
    37     [super viewDidLoad];
    38     UIButton *testConcurrentButton = [[UIButton alloc]initWithFrame:CGRectMake(10, 70, 145, 30)];
    39     [testConcurrentButton setTitle:@"开始售票" forState:UIControlStateNormal];
    40     [testConcurrentButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    41     testConcurrentButton.backgroundColor = [UIColor yellowColor];
    42     [testConcurrentButton addTarget:self action:@selector(startSale) forControlEvents:UIControlEventTouchUpInside];
    43     [self.view addSubview:testConcurrentButton];
    44 }
    45 
    46 - (void)didReceiveMemoryWarning {
    47     [super didReceiveMemoryWarning];
    48 }
    49 
    50 //一个窗口售票
    51 - (void)saleATicket:(const char *)cStr atWindow:(int)w
    52 {
    53     dispatch_queue_t queue = dispatch_queue_create(cStr, DISPATCH_QUEUE_CONCURRENT);
    54     dispatch_async(queue, ^{
    55         while (_ticketsCount > 0) {
    56             
    57             @synchronized(self) {
    58                 _ticketsCount -- ;
    59                 NSLog(@"此次出票成功,还有%lld张余票,售票处%d",_ticketsCount,w);
    60             }
    61 
    62 //            [_myLock lock];
    63 //            _ticketsCount -- ;
    64 //            NSLog(@"此次出票成功,还有%lld张余票,售票处%d",_ticketsCount,w);
    65 //            [_myLock unlock];
    66 //            
    67 //            pthread_mutex_lock(&sDefaultMutex);
    68 //            _ticketsCount -- ;
    69 //            NSLog(@"此次出票成功,还有%lld张余票,售票处%d",_ticketsCount,w);
    70 //            pthread_mutex_unlock(&sDefaultMutex);
    71 //            
    72 //            OSSpinLockLock(&_spinLock);
    73 //            _ticketsCount -- ;
    74 //            NSLog(@"此次出票成功,还有%lld张余票,售票处%d",_ticketsCount,w);
    75 //            OSSpinLockUnlock(&_spinLock);
    76             
    77             //下一个顾客,暂停500ms
    78             sleep(2);
    79         }
    80         
    81         if (_ticketsCount <= 0) {
    82             NSLog(@"票已售完");
    83         }
    84     });
    85 }
    86 
    87 - (void)startSale
    88 {
    89     
    90     for (int i = 0; i < salesGirls; i++) {
    91         NSString *str = [NSString stringWithFormat:@"com.sale.%d%d",i,i];
    92         [self saleATicket:[str UTF8String] atWindow:i];
    93     }
    94 }
    95 @end
    View Code

    二、性能测试:

     1 -(void)testPerformance
     2 {
     3     CFAbsoluteTime startTime,endTime;
     4     int i = 0;
     5     
     6     startTime = CFAbsoluteTimeGetCurrent();
     7     for (i = 0 ; i < RUNCOUNT; i++) {
     8         @synchronized(self) {
     9             
    10         }
    11     }
    12     endTime = CFAbsoluteTimeGetCurrent();
    13     NSLog(@"totalTime synchronized = %f sec", endTime - startTime);
    14     
    15     
    16     NSLock *myL = [NSLock new];
    17     startTime = CFAbsoluteTimeGetCurrent();
    18     for(i= 0;i <RUNCOUNT ;i++){
    19         [myL lock];
    20         [myL unlock];
    21     }
    22     endTime = CFAbsoluteTimeGetCurrent();
    23     NSLog(@"totalTime NSLock = %f sec", endTime - startTime);
    24     
    25     
    26     startTime = CFAbsoluteTimeGetCurrent();
    27     for(i= 0;i <RUNCOUNT ;i++){
    28         pthread_mutex_lock(&sDefaultMutex);
    29         pthread_mutex_unlock(&sDefaultMutex);
    30     }
    31     endTime = CFAbsoluteTimeGetCurrent();
    32     NSLog(@"totalTime pthread = %f sec", endTime - startTime);
    33     
    34     
    35     startTime = CFAbsoluteTimeGetCurrent();
    36     for(i= 0;i <RUNCOUNT ;i++){
    37         OSSpinLockLock(&_spinLock);
    38         OSSpinLockUnlock(&_spinLock);
    39     }
    40     endTime = CFAbsoluteTimeGetCurrent();
    41     NSLog(@"totalTime OSSpinLock = %f sec", endTime - startTime);
    42 }
    View Code

    执行1024*1024*1024次空锁的时间是:

    执行1024*1024*32次空锁的时间是:

    可以看出,几种锁性能相差较大,性能 OSSpinLock > pthread > NSLock >synchronized 

    三、性能分析

    为什么几种锁的性能有如此明显的差异,它们的实现方式有何差别?

    So, what makes @sychronized and SpinLock so different from the others?

    @synchronized is very heavy weight because it has to set up an exception handler, and it actually ends up taking a few internal locks on its way there.  So instead of a simple cheap lock, you’re paying for a couple locks/unlocks just to acquire your measly lock.  Those take time.

    OSSpinLock, on the other hand, doesn’t even enter the kernel — it just keeps reloading the lock, hoping that it’s unlocked.  This is terribly inefficient if locks are held for more than a few nanoseconds, but it saves a costly system call and a couple context switches.  Pthread mutexes actually use an OSSpinLock first, to keep things running smoothly where there’s no contention.  When there is, it resorts to heavier, kernel-level locking/tasking stuff.

    So, if you’ve got hotly-contested locks, OSSpinLock probably isn’t for you (unless your critical sections are _Really_ _Fast_).  Pthread mutexes are a tiny bit more expensive, but they avoid the power-wasting effects of OSSpinLock.

    NSLock is a pretty wrapper on pthread mutexes.  They don’t provide much else, so there’s not much point in using them over pthread mutexes.

    Of course, standard optimization disclaimers apply:  don’t do it until you’re sure you’ve chosen the correct algorithms, have profiled to find hotspots, and have found locking to be one of those hot items.  Otherwise, you’re wasting your time on something that’s likely to provide minimal benefits.

  • 相关阅读:
    关于HDFS默认block块大小
    从计算框架MapReduce看Hadoop1.0和2.0的区别
    Linux的作业管理
    php 随机密码和盐 来自wordpress
    SSH管理(重启 停止 运行 安装)centos7
    卸载iptables 小心了!!怎么关闭和卸载iptables
    mysqld: Out of memory 解决办法(mysql)
    ie6 ie7 ie8 ie9兼容问题终极解决方案
    call_user_func()的参数不能为引用传递 自定义替代方法
    centos 域名硬解析(linux)
  • 原文地址:https://www.cnblogs.com/wyqfighting/p/5141641.html
Copyright © 2011-2022 走看看