并发C ++应用程序的最佳实践

时间:2014-09-17 16:32:54

标签: c++ multithreading design-patterns concurrency

我对设计并发C ++应用程序的软件设计方面有一些疑问。我有一些高级问题(我知道基本知识,如'什么是锁/互斥/条件变量'等)。

锁定功能层次结构

假设某些函数func对某个对象obj起作用。在这些操作期间,有必要持有一个锁(可能是obj的成员变量)。现在假设 func在持有锁时调用子功能func_2。现在func_2对已经锁定的对象进行操作。但是,如果我还想在没有按住锁的情况下从其他地方拨打func_2该怎么办?应该func_2锁定obj还是不应该?我看到3个可能性:

  1. 我可以将bool传递给func_2,表明是否需要锁定。 这似乎引入了很多样板代码。
  2. 我可以使用递归锁定,并始终在obj中锁定func_2。递归锁 好像 但是有问题,请参阅here
  3. 我可以假设func_2的每个来电者都已拥有锁。我会 记录这个并且可能强制执行此操作(至少在调试模式下)。是 让函数做出关于哪些锁是否锁定的假设是合理的 由调用线程持有?更一般地说,我如何从设计角度做出决定 哪个函数应该锁定Obj哪个函数应该假定它已被锁定?
  4. 你对此有什么建议吗?

    公开锁定/互斥

    到目前为止,我正在使用一种返回Mutex&的方法,我将其提供给RAII Lock。我认为,如果我使用C ++ 11,那么直接返回Lock并重载移动构造函数将更加白痴。但这在C ++ 03中是不可能的。不过,是否存在不同的策略? 通常建议暴露互斥体还是应该避免使用?

    对象层次结构

    假设我有一个由多个页面组成的文档。可以通过以下方式访问此文档:

    1. 用户通过更改/删除/插入/复制页面进行交互
    2. 线程重新呈现可见/已更改/等的页面
    3. 显而易见的方法是对文档进行大锁定,每个线程在访问文档时都必须保留。这具有明显的缺点,即渲染线程基本上连续工作,即使它们访问不同的页面。我有两个解决方案:

      1. 使用读写互斥锁。在修改文档时,线程必须具有写访问权 而重新呈现的线程只需要读访问权。
      2. 为每个页面使用一个锁加一个文档。重新渲染线程持有Page 锁。用户线程在更改页面时获取页面锁定,另外还有 文档锁定时更改Document的结构。 如果用户想要进行交换,可能需要保留多个页面锁定 两页。在这种情况下,我认为必须有一个固定的锁定顺序。
      3. 这些方法如何比较代码复杂性/执行时间?你会推荐什么?

        跨线程锁定

        再次考虑最后一点的情景。假设对任务和线程有一些亲和力。更重要的是,某些函数只需要从特定的线程调用(如果你必须知道我使用的是gtk,并且需要与gtk的任何交互必须从单个线程执行。)。方法似乎是添加一个由正确的线程处理的回调。但是,如果我在整个操作期间需要锁定,会发生什么?我是否应该通过线程传递(保持)锁定(这对我来说似乎是一种反模式)?

        单线程支持

        为了查找错误,我希望有一个单线程模式。假设我有一个调度程序 使用Runnable方法传递run类实例。通常,Scheduler充当Threadpool。它会通知一些空闲线程并将其传递给要处理的实例。我有一个天真的想法,让调度程序只调用run方法本身。但这不起作用,因为调用函数可能会保存Runnable需要锁定的锁,从而导致死锁。有一些简单的方法可以避免这种情况吗?我很想把一个bool传递给锁,指示锁只是一个假人,应该什么都不做。但这可能只是将多线程问题(违反不变量)引入单线程环境......是否有一些简单的方法可以让Scheduler切换到单线程模式?

        这些都是一些问题,我花了一段时间写下来:) 我非常感谢你的帮助。对文献的建议会 也欢迎。

0 个答案:

没有答案