1. 程式人生 > >iOS學習——鎖

iOS學習——鎖

方式 targe 賦值 void art getter pre select 在線

  在多線程學習中,必然會涉及到不同線程對同一資源的調取,面對這種調用不加以控制,就會產生數據混亂的情況。最常見的情況莫過於買票,多個售票員售票肯定是同時操作,這樣就會開啟多條線程,但是這種售票方式會產生票數不對的情況。

- (void)demo1 {
    //售票員A
    NSThread *threadA = [[NSThread alloc] initWithTarget:self selector:@selector(sellTikets) object:nil];
    threadA.name = @"threadA";
    [threadA start];
    
    
//售票員B NSThread *threadB = [[NSThread alloc] initWithTarget:self selector:@selector(sellTikets) object:nil]; threadB.name = @"threadB"; [threadB start]; } - (void)sellTikets{ while (YES) { if (self.tiketNum > 0) { self.tiketNum -- ; NSLog(
@"還剩%d張票 %@",self.tiketNum,[NSThread currentThread]); }else { NSLog(@"票賣完了 %@",[NSThread currentThread]);           break; } } }
技術分享
這裏對於第九張票出售了兩次,這就是用多線程產生的數據不安全問題,因為在多線程的資源共享中,就得上一把鎖來保證不會出現這種問題
- (void)sellTikets{
        while (YES) {
            @synchronized(self) {
                
if (self.tiketNum > 0) { self.tiketNum -- ; NSLog(@"還剩%d張票 %@",self.tiketNum,[NSThread currentThread]); }else { NSLog(@"票賣完了 %@",[NSThread currentThread]); break; } } } }
  @syn中需要傳一個全局變量參數,不一定是self,但是一定不能傳一個局部變量,因為這裏的參數作為一個鎖,要保證在線程執行的整個過程中都能鎖住線程,如果是一個局部變量,線程運行一次就被釋放掉了,根本毫無意義。
  互斥鎖保證了線程在運行中,每次只有一個線程能訪問到被鎖住的代碼塊,其他需要訪問的線程則在鎖外面睡眠等待,當一個線程執行完畢,才有下一個線程的執行。那麽,我們就得提到OC中的另外一個概念,原子性 atomic。在變量的聲明時,我們大多是情況下都是用nonatomic,用以提高運行效率,那麽atomic的作用在哪裏呢?一般我們在寫文件的時候,會使用這樣的代碼:
    NSData*data = [@"iosSynChronized" dataUsingEncoding:NSUTF8StringEncoding];
    [data  writeToFile:@"ios.text" atomically:YES];
  為了保證文件寫入時候的安全,我們一般會選擇使用原子性。這樣,當文字在寫入的時候並不是直接創建一個本地文件寫數據,而是創建一個虛擬文件,當數據寫入完成,然後一次性形成要存儲的本地文件,就不會出現,寫入的時候你刪除文件,修改文件造成的數據沖突。類似於一個鎖一樣,鎖住你要操作的東西,只有完成才能結束。同樣,給變量聲明atomic也就等於給變量賦值創建了一把鎖,只有一個線程完成對該變量的操作,下一個線程才能進行:
@property (atomic, strong) NSObject *lock;
@end

@implementation ViewController
@synthesize lock = _lock;//重新getter和setter方法後,xcode就不會自動幫寫成員變量
-(void)setLock:(NSObject *)lock {
    @synchronized (self) {
        _lock = lock;
    }
}
- (NSObject *)lock {
    return _lock;


  鎖能夠保證數據安全,但同樣也因此帶來了極大的不便,那就是效率問題,它將所有訪問操作都變成了單一操作,會浪費大量時間,這也是蘋果的UIKIT同樣采用線程不安全方式的原因,考慮到了效率問題。

 

iOS學習——鎖