Is it safe to use as a member function of one clas

2019-09-18 02:16发布

For example:

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?

5条回答
贪生不怕死
2楼-- · 2019-09-18 02:44

Only if there are some mutex to locked and synchronized in your working.

查看更多
做自己的国王
3楼-- · 2019-09-18 02:51

It depends on the code in the method. If there are no races in the method it is fine. There are non in your example since there is no code ;)

In your example, "a" might get destroyed before the threads exit (if the user is fast).

查看更多
We Are One
4楼-- · 2019-09-18 02:55

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;
};

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;
};

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.

查看更多
女痞
5楼-- · 2019-09-18 02:57

If neither run1() nor run2() changes a member variable of a or that variable is never used afterwards, then yes, it is safe. A more generic word for it is stateless.

查看更多
爷、活的狠高调
6楼-- · 2019-09-18 03:01

The question is fairly general, and I feel the example you give doesn't match the question.

In any non-trivial application then yes, you do need to synchronize access to instance variables unless you can guarantee that an instance of the class will never be accessed from different threads.

About methods and threads; local variables in a method reside on the stack and as such are inherently thread-safe. If the method accesses instance variables that method is not inherently thread-safe.

查看更多
登录 后发表回答