Objective-C 2.0中的多线程问题
我有我的主应用程序委托,其中包含一个返回对象的方法。该应用程序委托在主线程上运行。
我还有一个在不同线程上运行的 NSOperation。除了希望有时能够在主线程上调用我的应用程序委托方法之外,我还需要从 NSOperation 线程中调用它以获取它返回的对象。我的第一个问题是,如果我从其他线程调用这个方法……
id newObject = [[[UIApplication sharedApplication] delegate] myMethod];
该方法是否会在与 NSOperation 相同的线程上处理,或者是否会与应用程序委托所在的线程(主线程)相同?
我还想确保 myMethod
中的代码一次仅由我的操作线程或主线程调用一次。我可以在我的应用程序委托中创建一个 NSLock 实例 var 并执行类似以下操作:
-(id)myMethod {
[myLock lock];
myObject = // Get or create my object to return
[myLock unlock];
return myObject;
}
感谢您的帮助!
麦克风
I have my main application delegate which contains a method that returns an object. This application delegate runs on the main thread.
I also have a NSOperation that gets run on a different thread. As well as wanting to be able to call my app delegate method on my main thread sometimes, I also need to call it from my NSOperation thread to get the object that it returns. My first question is, if I call this from my other thread...
id newObject = [[[UIApplication sharedApplication] delegate] myMethod];
... will that method be processed on the same thread as the NSOperation, or will it be the same thread (main) as the application delegate is on?
I also want to make sure that the code within myMethod
is only called once at a time by either my operation thread or my main thread. Can I just create a NSLock instance var in my application delegate and do something like:
-(id)myMethod {
[myLock lock];
myObject = // Get or create my object to return
[myLock unlock];
return myObject;
}
Thanks for your help!
Mike
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
除非您显式编写代码以导致某些内容在另一个线程上执行,否则每个方法调用都将直接在调用它的线程上执行。方法调用没有什么魔力。您可以将其视为具有与用于线程目的的 C 函数调用完全相同的语义/ABI。
您的锁定模式可以很好地确保跨线程的独占访问。
另外两个不相关的注释(因为很多人都被它绊倒了):
将属性声明为
atomic
与线程安全关系不大。原子性仅保证您获得有效值,而不是正确值(这是有区别的)。自动释放的对象在线程之间传递永远不安全。您需要在发送线程上显式保留并在接收线程上平衡最终释放。
Unless you explicitly write code to cause something to execute on another thread, every method call is going to be executed directly on the thread it was called upon. There is no magic with a method call. You can think of it as having the exact same semantics/ABI as a C function call for the purposes of threading.
Your locking pattern will work fine to ensure exclusive access across threads.
Two additional unrelated notes (because so many people trip over it):
declaring a property as
atomic
has little to do with thread safety. Atomicity only guarantees that you get a valid value, not the correct value (there is a difference).autoreleased objects are never safe to pass between threads. You need an explicit
retain
on the sending thread and a balancing eventualrelease
on the receiving thread.您是否绝对需要在 NSOperation 线程上执行此调用,而不是简单地提供所需的对象作为创建自定义操作的一部分?
如果是这样,我建议不要使用锁,除非性能至关重要。如果 iPhone 支持它,您可以使用 Grand Central Dispatch 将对象获取到您的线程中:
对于 iPhone,我很想创建一个辅助方法:
并像这样从您的
NSOperation
线程中调用它:实际上在主线程上执行的隐含风险较小。
Do you absolutely need to perform this invocation on the
NSOperation
thread, and not simply provide the required object as part of creating the custom operation?If so, I would recommend not using locks unless performance is critical. If the iPhone supported it, you could use Grand Central Dispatch to get the object onto your thread:
For the iPhone, I would be tempted to create a helper method:
And invoke it like so from your
NSOperation
thread:Actually performing the execution on the main thread has fewer implicit risks.
如果您只需要保护代码的关键部分,为什么不使用 Objective-C @synchronized 指令呢?当然,使用 NSLock 也可以,但是你需要显式管理 NSLock 实例。从文档来看:
Objective-C 支持应用程序中的多线程。这意味着两个线程可以尝试同时修改同一个对象,这种情况可能会导致程序出现严重问题。为了防止一段代码同时被多个线程执行,Objective-C 提供了 @synchronized() 指令。
@synchronized() 指令锁定一段代码以供单个线程使用。其他线程将被阻塞,直到该线程退出受保护的代码;也就是说,当执行继续经过 @synchronized() 块中的最后一条语句时。
@synchronized() 指令将任何 Objective-C 对象(包括 self)作为其唯一参数。该对象称为互斥信号量或互斥体。它允许线程锁定一段代码以防止其他线程使用它。您应该使用单独的信号量来保护程序的不同关键部分。在应用程序变为多线程之前创建所有互斥对象以避免竞争条件是最安全的。
清单 12-1 显示了使用 self 作为互斥体来同步对当前对象的实例方法的访问的代码示例。您可以采用类似的方法来同步关联类的类方法,使用 Class 对象而不是 self。当然,在后一种情况下,一次只允许一个线程执行类方法,因为只有一个类对象由所有调用者共享。
清单 12-1 使用 self 锁定方法
If you simply need to protect a critical section of code, why not using the Objective-C @synchronized directive? Of course, using NSLock will also work, but you need to explicitly manage the NSLock instance. From the documentation:
Objective-C supports multithreading in applications. This means that two threads can try to modify the same object at the same time, a situation that can cause serious problems in a program. To protect sections of code from being executed by more than one thread at a time, Objective-C provides the @synchronized() directive.
The @synchronized()directive locks a section of code for use by a single thread. Other threads are blocked until the thread exits the protected code; that is, when execution continues past the last statement in the @synchronized() block.
The @synchronized() directive takes as its only argument any Objective-C object, including self. This object is known as a mutual exclusion semaphore or mutex. It allows a thread to lock a section of code to prevent its use by other threads. You should use separate semaphores to protect different critical sections of a program. It’s safest to create all the mutual exclusion objects before the application becomes multithreaded to avoid race conditions.
Listing 12-1 shows an example of code that uses self as the mutex to synchronize access to the instance methods of the current object. You can take a similar approach to synchronize the class methods of the associated class, using the Class object instead of self. In the latter case, of course, only one thread at a time is allowed to execute a class method because there is only one class object that is shared by all callers.
Listing 12-1 Locking a method using self