本文介绍了它是安全的,因为一类在不同的线程成员函数使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如:

struct A {
void run1() {}
void run2() {}
};

int main()
{
  A a;

  thread t1(bind(&A::run1, ref(a)));
  thread t2(bind(&A::run2, ref(a)));

  // not joinable thread!

  int i;
  std::cin >> i;
}

和请看看下面这个例子

And please look at this example http://developer.gnome.org/glibmm/unstable/thread_2thread_8cc-example.html

请问 对象应该由互斥体还是别的什么保护?难道就没有竞争条件吗?

Does the a object should be protected by mutex or something else? Is there no race condition here?

推荐答案

问题的答案取决于类。如果方法不共享相同的实例变量的访问不需要同步。这是因为该方法调用机制本质上是线程安全的,因为它没有修改的对象。如果他们共享访问,需要同步。就拿这个类,例如:

The answer depends on the class. If the methods don't share access to the same instance variables you don't need synchronization. That's because the method call mechanism is inherently thread-safe as it doesn't modify the object. If they do share access, you need synchronization. Take this class for example:

class A
{
public:
  void inc () { x++; }
  void dec () { x--; }

private:
  int x;
};

如果多个线程被允许调用的同时方法,你需要保护的X与互斥。有几种可能的策略。之一是使类线程安全。这将是这样的:

If several threads are allowed to call A's methods at the same time, you need to protect the x with a mutex. There are several possible strategies. One is to make the class thread-safe. That would look like this:

class A
{
  public:
  void inc () {
    m.lock();
    x++;
    m.unlock();
  }

  void dec () {
    m.lock();
    x--;
    m.unlock();
  }

private:
  int x;
  mutex m;
};

这里的好处是,来电者不必担心同步。缺点是如果类永远只从一个线程调用的性能损失。你也有一个问题,如果你需要保证一个线程可以调用连续几种方法,而不从另一个线程的干扰。在这种情况下,调用线程需要使用前看的类。它是这样的:

The advantage here is that callers don't have to worry about synchronization. The downside is the performance penalty if the class is only ever called from one thread. You also have an issue if you need to guarantee that a thread can call several methods in a row without interference from another thread. In this case the calling thread need to look the class before using it. It would look like this:

class A
{
  public:
  void lock () { m.lock(); }
  void unlock () { m.unlock(); }
  void inc () { x++; }
  void dec () { x--; }

private:
  int x;
  mutex m;
};

来电者必须然后包装方法调用在A ::锁()/ A ::解锁()对。如果你需要使用没有考虑线程安全写了一个类,你需要将对象之外创建一个互斥体,并把它作为在previous例子。或者你可以创建一个线程安全的包装。当然缺点是,这是容易出错的。

The callers must then wrap method calls in a A::lock()/A::unlock() pair. If you need to use a class that was not written with thread-safety in mind you need to create a mutex outside the object and use it as in the previous example. Or you can create a thread-safe wrapper. The downside of course is that this is error-prone.

请注意,您也可以同时提供锁定和解锁访问:

Note that you can also offer both locked and unlocked access:

class A
    {
      public:
      void lock () { m.lock(); }
      void unlock () { m.unlock(); }
      void inc_unlocked () { x++; }
      void dec_unlocked () { x--; }
      void inc () { m.lock(); inc_unlocked(); m.unlock(); }
      void dec () { m.lock(); dec_unlocked(); m.unlock(); }

    private:
      int x;
      mutex m;
    };

如果类在使用解锁版本的性能单线程应用程序中使用这种方式,否则您使用锁定的版本或包裹在锁()/解锁解锁版本()调用。这是两全​​其美,以增加复杂性为代价。

This way if the class is used in a single thread application you use the unlocked versions for performance otherwise you use either the locked versions or the unlocked versions wrapped in lock()/unlock() calls. That is the best of both worlds, at the cost of an increase in complexity.

如何在这些选项之间选择的是品味和经验的问题。

How to choose between these options is a matter of taste and experience.

这篇关于它是安全的,因为一类在不同的线程成员函数使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 18:15