作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
假设您有一个可以被多个线程访问的对象。临界区用于保护敏感区域。但是析构函数呢?即使我一进入析构函数就进入临界区,一旦调用了析构函数,对象就已经失效了吗?
我的思路:假设我进入析构函数,我必须在临界区等待,因为其他线程仍在使用它。一旦他完成,我就可以完成销毁该对象。这有意义吗?
最佳答案
一般来说,你不应该销毁一个对象,直到你知道没有其他线程正在使用它。期间。
根据您的“思路”考虑这种情况:
现在考虑如果时间略有不同会发生什么:
简而言之,对象销毁必须在对象本身以外的某个地方同步。一种常见的选择是使用引用计数。线程 A 将锁定对象引用本身,以防止引用被删除和对象被销毁,直到它设法增加引用计数(使对象保持事件状态)。然后线程 B 只是清除引用并减少引用计数。您无法预测哪个线程将实际调用析构函数,但无论哪种方式都是安全的。
使用boost::shared_ptr
可以很容易地实现引用计数模型。或 std::shared_ptr
;除非所有线程中的所有 shared_ptr
都被销毁(或指向其他地方),否则析构函数不会运行,因此在销毁的那一刻,您知道唯一指向剩余对象的指针是 this
析构函数本身的指针。
请注意,在使用 shared_ptr 时,重要的是要防止原始对象引用发生更改,直到您可以捕获它的拷贝。例如:
std::shared_ptr<SomeObject> objref;
Mutex objlock;
void ok1() {
objlock.lock();
objref->dosomething(); // ok; reference is locked
objlock.unlock();
}
void ok2() {
std::shared_ptr<SomeObject> localref;
objlock.lock();
localref = objref;
objlock.unlock();
localref->dosomething(); // ok; local reference
}
void notok1() {
objref->dosomething(); // not ok; reference may be modified
}
void notok2() {
std::shared_ptr<SomeObject> localref = objref; // not ok; objref may be modified
localref->dosomething();
}
请注意,shared_ptr
上的同时读取 是安全的,因此如果对您的应用程序有意义,您可以选择使用读写锁。
关于C++:并发和析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6710129/
我是一名优秀的程序员,十分优秀!