Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在同一列表上的多线程中避免空指针?_C++_Multithreading - Fatal编程技术网

C++ 如何在同一列表上的多线程中避免空指针?

C++ 如何在同一列表上的多线程中避免空指针?,c++,multithreading,C++,Multithreading,比如说,我有一个动态对象指针向量,并且有不同的线程处理这些对象 当一个线程处理一个对象时,主线程可能正在删除它。它通过在对象中设置一个标志来标记它要删除,然后开始释放它的内存来实现这一点 我曾考虑过在每次访问对象之前检查标志来解决这个问题,但理论上可能会发生以下情况(示例代码用于说明,尽管我试图使其尽可能最好地反映情况,但其中仍可能存在错误): 虽然这可能是罕见的,但这当然仍然是不可接受的。作为一个显然对多线程非常生疏的人,解决这个问题的正确方法是什么?请注意:我假设您了解同步(互斥体、条件变量

比如说,我有一个动态对象指针向量,并且有不同的线程处理这些对象

当一个线程处理一个对象时,主线程可能正在删除它。它通过在对象中设置一个标志来标记它要删除,然后开始释放它的内存来实现这一点

我曾考虑过在每次访问对象之前检查标志来解决这个问题,但理论上可能会发生以下情况(示例代码用于说明,尽管我试图使其尽可能最好地反映情况,但其中仍可能存在错误):


虽然这可能是罕见的,但这当然仍然是不可接受的。作为一个显然对多线程非常生疏的人,解决这个问题的正确方法是什么?

请注意:我假设您了解同步(互斥体、条件变量、原子等),即用于多线程编程的基本构建块,您的问题是如何使用它们。你需要这些基础知识

你的问题基本上是所有权不明确。当程序的一部分正在销毁一个共享对象,而另一部分仍在使用它时,这是因为它错误地认为它是唯一的所有者,并且可以处置该对象。更一般地说,在多线程中,您也可以说它在不同步的情况下更改数据结构,但这种情况非常特殊,有相应的工具来处理它

处理此问题的工具称为引用计数和垃圾收集。其中,最容易应用的可能是引用计数。为此,您只需要一个智能指针,它可以跟踪对象所有者的数量。例如,
std::shared_ptr
正好提供了这一点,它以线程安全的方式管理引用计数。为了从提到的向量中“删除”一个对象,您只需删除智能指针。如果refcount变为零,则它是最后一个,并为您删除


垃圾收集有点复杂。它涉及到扫描进程内存中的对象引用/指针,以及删除不再引用的对象。不过,这需要安装垃圾收集器,而且对现有程序来说,这是一个更复杂的更改。

您可以在执行检查之前获取对象的互斥锁,也可以使用习惯用法。请注意:您编写了“主线程”,但在大多数线程环境中都没有这样的东西。特别是,线程之间没有父子关系或主从关系。即使运行
main()
的线程也只是一个线程。可能唯一的区别在于运行
main()
的线程终止时会发生什么。@UlrichEckhardt提到主线程只是为了强调它是一件完全不同的事情,而不是管理线程副本的同步。我个人会考虑负责管理其他线程的线程,即线程池的“主线程”或“管理线程”。如果这是选择术语的错误方法,请纠正我。我想补充一点,即只有
shared\u ptr
的参考计数器是“原子的”。仍然必须管理对对象的访问。这经常被忘记,这导致了UB。谢谢你的回答,我必须承认我理解它有点困难。例如,我看不出垃圾收集与同步有什么关系。另外,当另一个线程仍在处理某个对象时,处理该对象实际上应该是预期的行为,在这种情况下,另一个线程检测到该对象并停止该对象上的工作/终止(以当前需要的为准,具体取决于线程本身的编程方式)(或被终止/告知跳过,以约定/尝试和信任的方式为准)。
object = copyPointerFromVector(someIndex);

if(!object->markedForDeletion){
---flag set, object cleaned up by main thread and erased from vector 
  object->getValues(something); //crash with access violation
}