@synchronized 会阻塞整个线程吗

Posted

技术标签:

【中文标题】@synchronized 会阻塞整个线程吗【英文标题】:Does @synchronized block a whole thread 【发布时间】:2012-05-21 09:27:42 【问题描述】:

说你愿意

MyLock *lock = [[MyLock new] autorelease];
@synchronized(lock) 
    NSLog(@"Hello World");
//some very long process

在主线程中。这是否意味着直到//一些非常长的过程完成,主线程被锁定?如果有其他线程调用

    //Update on the main thread
    dispatch_sync(dispatch_get_main_queue(), ^
        //Do some updates
    );

有些更新永远不会被调用?我说的对吗?

【问题讨论】:

【参考方案1】:

如果第一个代码 sn-p 中的代码从未完成,则不会调用第二个代码,无论 @synchronized 语句如何。该线程被您正在执行的代码阻塞。 @synchronized 语句用于同步多个线程之间的数据访问,它要求所有参与的线程实际使用该语句。它不会“神奇地”锁定对数据结构的访问,除非所有参与线程“同意”它。

您不要使用@synchronized 来确保在给定(单个)线程上只执行一个方法,无论如何都是这样。

为了给你一个具体的使用例子,假设你有一个NSMutableArray,你想防止它同时被不同的线程修改(这可能导致数据损坏)。在这种情况下,您始终可以使用相同的锁定令牌在 @synchronized 块中访问它。

例子:

//Thread 1:
@synchronized (myArray) 
    [myArray addObject:@"foo"];


//Thread 2:
@synchronized (myArray) 
    [myArray removeObjectAtIndex:0];

这将确保@synchronized 所包含的代码块永远不会同时执行。当一个线程进入块时,其他线程会一直等待直到它完成,但只有在它们也使用相同的@synchronized 语句。如果您忘记在一个线程上使用它,那么如果您在另一个线程上使用它就没有任何帮助。

【讨论】:

【参考方案2】:

简短的回答是否定的。我认为您不了解锁定的概念。您应该在这里阅读更多关于同步的信息:

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html

当您访问您试图保护的代码时,您必须在每种情况下使用相同的锁定对象(相同的实例!)进行同步。您可以将锁定对象存储为类的属性。

在你的情况下:

self.lock = [[MyLock new] autorelease]; //in init method initialize retain or strong lock property

...
@synchronized(self.lock) 
   NSLog(@"Hello World");
   //some very long process



//Update on the main thread
dispatch_sync(dispatch_get_main_queue(), ^
   @synchronized(self.lock) 
      NSLog(@"Hello World");
      //some very long process
   
);

如果您可以用作锁定对象,您正在尝试保护的对象。

【讨论】:

以上是关于@synchronized 会阻塞整个线程吗的主要内容,如果未能解决你的问题,请参考以下文章

java synchronized关键字的底层实现

Java多线程同步方法

多线程下的锁

多线程

多线程同步

JAVA中线程同步的方法(7种)汇总