zl程序教程

您现在的位置是:首页 >  其他

当前栏目

浅谈iOS @synchronized 锁用法

2023-03-15 23:21:34 时间

接触开发稍微深一点的人都应该知道锁的概念,所谓锁,就是在操作数据的时候,为了防止多个操作同时操作一个数据导致数据的错乱或者非即时而采用的一种规避手段。

尤其在使用多线程进行开发时,由于多个线程的操作可能会同时对某个数据进行操作,可能是读也可能是写,如果不加以处理,那么可能在一个线程读的时候另一个线程去写,读的线程得到的数据就可能不是最新的数据,或者两个线程同时对数据进行修改,导致一些不可预知的错乱。

这时候就应该加一道锁,在A线程操作数据的时候,将数据给锁住,锁住的意思也就是不允许其他线程来操作这个数据,想操作的都得进行等待,直到 A操作完了,才将锁给打开,这时才允许其他线程排队进行操作。

说到锁,还有个概念不得不说,那就是信号量,信号量是用来控制加锁解锁的,比如说一个变量,为0表示当前无人操作,为1表示当前有人操作,那么当一个线程要操作时,先看这个信号量是不是0,是0就可以操作, 是1就得等待,这事一种信号量的形式,还有多种形式。

在iOS开发中多线程也是经常用到的东西,因此对于一些关键的代码就有必要加锁。iOS 中加锁有多种方式,比如:

  • NSLock
  • dispatch_semaphore_wait
  • @synchronized

本文要说的就是最后一种 @synchronized 的用法。其实 @synchronized 用法很简单,首先 @synchronized() 小括号内需要一个参数,这个参数就表示信号量。这个参数可以是任何对象,包括 self,或者是自定义的信号量。针对不同的操作应该定义不同的信号量。

@synchronized() {...} 大括号中就是要加锁执行的代码,代码会操作一些数据。当开始执行代码时,意味着当前线程对其加锁了,当代码执行完后,自动解锁,其他线程才允许执行此段代码。

下面是用 self 作为信号量来加锁的示例,也就是在当前实例中对此代码块操作要加锁:

-(void)importantMethod  
{  
    @synchronized(self)  
    {  
        // 关键代码;  
    }  
}  

下面是使用自定义的信号量来加锁的示例:

-(void)importantMethod  
{  
    Account *account = [AccountaccoutFromString :[accountFiled stringValue]];  
       
    //获取信号量  
    id accountSemaphore = [account semaphore];  
    @synchronized(accountSemaphore)  
    {  
        //关键代码  
    }  
}

值得一提的是这个加锁机制是支持递归的,如果加锁的代码在当前线程中递归调用自身,那么会持续保持加锁状态,其余线程还是访问不了,只有当递归完成全部执行完后,或者出错报异常退出后,锁才会解开,释放信号量,其余线程才允许操作此段代码块。