c ++多线程同步与不断变化的资源量
Posted
技术标签:
【中文标题】c ++多线程同步与不断变化的资源量【英文标题】:c++ multithreading synchronization with a changing amount of resources 【发布时间】:2018-07-06 13:11:53 【问题描述】:当资源数量未知/变化时,我很难找到同步线程的方法。问题:
有一个资源数组 R 在多个线程之间共享,每个线程可以执行 3 种操作之一:
创建一个新资源并将其添加到数组中(从而增加它的大小)。
从数组中删除一个资源(从而减小它的大小)。
访问资源(写入/读取它的值)。
每个操作都会向用户输出成功/失败消息。每个资源都有一个唯一的 ID。目的是允许尽可能多的并行性,因此不能为每个线程操作锁定所有资源(整个数组)。
这样做的一个问题是,每次线程向数组添加新资源时,它也需要为该资源创建一个锁,这就产生了一个问题,即在创建线程创建锁之后,锁可以在创建线程有时间初始化创建的资源值之前被访问线程抓取。
另一个问题是线程试图访问不存在的资源的情况,因此在这种情况下,它会检查资源是否存在,如果不存在则向用户输出错误消息,但在输出错误消息之前另一个线程创建资源(在访问线程检查资源是否存在之后),因此将在成功消息(混合顺序)之后输出错误消息。
我想听听有关如何处理此类问题的想法。 谢谢。
【问题讨论】:
听起来你需要一个线程安全的向量。除非你只取 from 并添加到后面,否则你可以使用无锁队列。 我写了一个无锁、固定容量的向量,但是限制比你需要的要多(多个线程可以添加元素,单个线程可以遍历元素并在遍历时删除它们)。不过,如果你有兴趣,就在这里:github.com/OlivierSohn/cpp.algorithms/blob/master/include/… 【参考方案1】:首先,当您从多个线程更改数组时,数组必须是线程安全的,因此为整个数组保留一个锁,并在执行这三个操作中的任何一个时获取它。
这样做的一个问题是,每次线程向数组添加新资源时,它也需要为该资源创建一个锁,这就产生了一个问题,即在创建线程创建锁之后,锁可以在创建线程有时间初始化创建的资源值之前被访问线程抓取。
对于这个问题,请确保每个线程在向其添加和初始化资源时锁定数组。如果初始化过程是一项耗时的任务,请在将资源添加到数组之前完成可以异步完成的部分。例如,如果你想将一个对象添加到数组中,这需要很长时间来初始化,并且可以异步初始化,首先创建并初始化该对象,然后锁定数组,同时将对象的指针添加到数组中。
另一个问题是线程试图访问不存在的资源时的场景,因此在这种情况下,它会检查资源是否存在,如果不存在则向用户输出错误消息,但在输出错误消息之前另一个线程创建资源(在访问线程检查资源是否存在之后),因此不会输出必要的错误消息。
我不确定在这种情况下你想做什么,如果你想让线程等待资源的创建,如果它不存在,使用条件变量,并且每次将资源添加到数组唤醒等待线程再次检查资源。
如果您不希望线程等待添加资源,但您的问题只是在用户收到错误时资源存在时输出“不存在”错误是不正确的,答案是:“没有问题!”。在我们检查它的那一刻,该资源不存在,并报告了一个错误。
更新:
由于您想同时访问多个资源,您应该锁定数组以访问该资源,然后锁定资源,然后在持有资源锁的同时释放数组的锁,但是一旦线程想要删除资源,它必须获取该资源的锁以确保没有其他线程正在使用它。
【讨论】:
【参考方案2】:这是一个标准的同步问题,只需使用 std::mutex (或 std::shared_mutex 如果可用且适当)控制对包含您的资源的 std::vector 的访问。如果你做得对,在你将整个互斥锁释放到向量之前,没有任何东西可以获取新的资源锁。
【讨论】:
如果您管理大量资源,我建议您使用 std::list。会有一些积极的方面,例如从列表中快速添加/删除元素,并且您不必重新索引来自等待线程的请求,因为它们始终指向正确的请求,除非资源丢失。 但我想允许线程同时访问数组中的不同资源,而不是为每个线程操作锁定整个数组 你能使用 shared_mutex 或 pthread 读/写锁吗? rw 锁可以在更新主向量时排除其他线程,然后每个元素都可以拥有自己的锁。当您不添加或删除资源时,每个人都可以获取接近免费的读锁。以上是关于c ++多线程同步与不断变化的资源量的主要内容,如果未能解决你的问题,请参考以下文章