【问题标题】:Protect class instances of multithreading access保护多线程访问的类实例
【发布时间】:2011-01-30 07:13:41
【问题描述】:

我有一个包含许多实例的 C++ 类,我想让我的应用程序线程安全。 这个类有一个成员和一个处理它的函数,例如:

class MyCls {
  int x;
  void f() { x++; }
};

我需要保护这个成员,所以据我所知,我有两个选择:

  1. 添加全局临界区和 在触摸此成员之前输入它。
  2. 向类添加关键部分 所以每个实例都会保护自己的成员。

这两种解决方案都是大材小用:

  1. 根本不应同步两个不同的实例。
  2. 操作系统应该处理数以百万计的关键部分,其中实际上很少有冲突。

我可以使用其他解决方案或多线程设计模式吗?

【问题讨论】:

  • 有些锁根本不需要任何特殊的初始化,只在线程阻塞时消耗资源。例如,这是微软的:msdn.microsoft.com/en-us/library/aa904937.aspx
  • 请使用 4 个缩进来格式化代码。
  • 为什么在这个问题上使用 C 标签?

标签: c++ c multithreading concurrency


【解决方案1】:

不确定,但我认为使用Software transactional memory 机制可以解决问题。有一堆implementations for C++

【讨论】:

【解决方案2】:

至于您的第一个问题,每个实例都应该有一个成员互斥锁,以便为每个实例提供一个单独的临界区。

至于第二个,我确信大多数 pthread 实现都使用futex 实现来作为它们的互斥锁。这意味着它们在没有争用时非常快,并且仅在出现争用时才需要操作系统干预。

【讨论】:

  • 核心思想应该是一样的。任何体面的操作系统都应该为具有很少开销的同步机制提供系统调用。任何提供同步抽象的库(如互斥锁)都应该正确使用它。我只是说我的个人经历。
【解决方案3】:

如果您不想使用锁或临界区,那么最简单的解决方案就是不要将状态保留在对象本身中。如果你像下面这样改变你的类,它将是线程安全的:

// Class has no state, only operations on data. So it
// is thread-safe by nature.
class MyCls 
{
    int foo(int x = 0)
    {
        return ++x;
    }
};

// Usage
MyCls obj;
int x = obj.foo(); // x = 1
x = obj.foo(x); // x = 2

【讨论】:

  • 这在某些情况下可能会奏效(这就是我没有投反对票的原因),但我认为我们(至少我)最想要的是我们的对象来封装它们的数据。
【解决方案4】:

如果你真的只需要增加那个成员(或类似的简单算术),你只需要原子操作。

  • 大多数(全部?)现代 CPU 都支持它们 带有原生指令。
  • 我不知道其他编译器, 但是来自 gcc 家族的人有 它们是内置的。

不幸的是,这些接口似乎没有标准化的接口,但即将到来的 C 标准 (C1x) 将拥有它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 2013-09-04
    • 2021-06-07
    • 2013-09-17
    • 1970-01-01
    相关资源
    最近更新 更多