【发布时间】:2023-03-30 20:54:02
【问题描述】:
在 C++ 下,我有一个Mutex 类,我使用这个 RAII 风格的类来确保互斥锁被解锁,不管方法返回的原因是什么:
class MutexLock {
protected:
Mutex &m_mutex;
public:
MutexLock(Mutex &mutex) :
m_mutex(mutex) {
m_mutex.lock();
}
~MutexLock() {
m_mutex.unlock();
}
};
是否有任何原因,并且在使用 ARC 时,等效的 Objective-C 类不能正常工作:
@interface Locker : NSObject {
NSLock *_lock;
}
- (void)setLock:(NSLock *)lock;
@end
@implementation Locker
- (void)setLock:(NSLock *)lock {
[_lock unlock];
_lock = lock;
[_lock lock];
}
- (void)dealloc {
self.lock = nil;
}
@end
可以通过以下方式使用:
NSLock *_lock; // instance variable
- (void)myFunc {
Locker *locker = [[Locker alloc] init];
locker.lock = _lock;
return; // Whenever I like
}
我知道它在 Objective-C 异常的情况下不起作用,这与 C++ 版本不同,但假设所有 Objective-C 异常都是致命的,我并不担心。
更新刚刚完成了一个快速测试,它似乎工作正常。看到这个gist。
【问题讨论】:
-
我想到的一件事是
[Locker lockerWithLock:_lock]可以返回一个自动释放的对象,当它超出范围时可能不会立即释放(取决于 ARC 编译器所做的优化)。 -
@MartinR 即使上面实现了
return [[Locker alloc] initWithLock:lock];? -
是的(我刚刚尝试过),因为您将其包装在
[Locker lockerWithLock:_lock]中。如果直接在myFunc中调用Locker *locker = [[Locker alloc] initWithLock:_lock],那么会立即释放。 -
@MartinR
Locker *locker = [[Locker alloc] init]; locker.lock = _lock;并在 setter 中执行锁定怎么样? (即摆脱类级别的便利方法)。 -
我会保留
initWithLocker:_lock并在init 方法中执行锁定,这与在dealloc 中解锁它非常对称。如果您只是关心“未使用的变量”警告,那么您可以在函数体的末尾添加locker = nil。
标签: c++ objective-c mutex raii