我有两个对象,A和B,彼此指向。
对象A可以通过一个线程删除,而对象B可以通过另一线程删除。
当删除对象A或B时,远程指针应设置为NULL(清除双向链接)。如何以安全可靠的方式实现此操作?
尽管描述起来很简单,但我认为它不容易实现。
天真的想法是用互斥量保护每个指针。但是,为了避免死锁,必须以相同的顺序锁定两个互斥锁。这将需要一个对象首先锁定远程互斥对象。但这意味着以不 protected 方式使用指针来访问远程锁。
到目前为止,我发现的唯一解决方案是使用由两个对象通过智能指针引用的一个共享互斥锁。当两个对象都被破坏时,互斥体也将被破坏。单个互斥锁可保护对双向链接的访问。因此,一次只能有一个线程可以修改双向链接并清除它。
有更好的方法吗?
编辑:用例的详细信息
数据结构:
______ _____ _____ ______
| | 1 N | | 1 1 | | N 1 | |
| A' | -----> | A | <-----> | B | <----- | B' |
|______| |_____| |_____| |______|
Thread_A thread_B
A'由Thread_A完全控制,而B'由Thread_B完全控制。 B'和Thread_B在我无法更改的库中。但是B是使用我提供给库的工厂方法构造的。因此,我完全控制了B的实现。
Thread_B可以随时删除B。因此,我无法控制B的生存期。Thread_A将在删除A'之前关闭库。这意味着Thread_B在Thread_A删除A'之前先删除所有B和B'对象。 Thread_A以固定的间隔扫描A的列表,并使用指向B的NULL指针擦除A。
在运行时,必须以这种方式传输数据A'-> A-> B-> B'。 Thread_A正在将数据存储在队列中,thread_B正在将数据从队列中拉出。我决定将队列放入B内,因为将数据存储在队列中的Thread_A是非阻塞操作。如果队列已满,则将丢弃数据。当Thread_B尝试从队列中提取数据时,它可能会绊倒在空队列上。库实现者要求Thread_B最多等待1秒并返回。
因此,我需要一种保护措施,以确保清除和测试双向链接状态,并在Thread_A将其数据存储在B中的队列中时阻止B的删除。
最佳答案
在通过@ Slava,@ SergeyA和@DanielStrul的注释进行了非常有帮助的讨论之后,我迫使我优化问题分析和描述,终于找到了解决方案。
对象A将始终在B之后被删除。因此,我可以将互斥锁存储在A中,以便Thread_A和Thread_B可以在其上安全地同步。
我不能使用weak_ptr,因为B的生命周期不受smart_ptr的控制。 B'持有指向B的原始指针,并且Thread_B调用delete B
。使用互斥锁,可以使用原始指针实现双向链接。