C++11 When To Use A Memory Fence?

2019-02-20 04:40发布

问题:

I'm writing some threaded C++11 code, and I'm not totally sure on when I need to use a memory fence or something. So here is basically what I'm doing:

class Worker
{
   std::string arg1;
   int arg2;
   int arg3;
   std::thread thread;

public:
   Worker( std::string arg1, int arg2, int arg3 )
   {
      this->arg1 = arg1;
      this->arg2 = arg2;
      this->arg3 = arg3;
   }

   void DoWork()
   {
      this->thread = std::thread( &Worker::Work, this );
   }

private:
   Work()
   {
      // Do stuff with args
   }
}

int main()
{
   Worker worker( "some data", 1, 2 );
   worker.DoWork();

   // Wait for it to finish
   return 0;
}

I was wondering, what steps do I need to take to make sure that the args are safe to access in the Work() function which runs on another thread. Is it enough that it's written in the constructor, and then the thread is created in a separate function? Or do I need a memory fence, and how do I make a memory fence to make sure all 3 args are written by the main thread, and then read by the Worker thread?

Thanks for any help!

回答1:

The C++11 standard section 30.3.1.2 thread constructors [thread.thread.constr] p5 describes the constructor template <class F, class... Args> explicit thread(F&& f, Args&&... args):

Synchronization: the completion of the invocation of the constructor synchronizes with the beginning of the invocation of the copy of f.

So everything in the current thread happens before the thread function is called. You don't need to do anything special to ensure that the assignments to the Worker members are complete and will be visible to the new thread.

In general, you should never have to use a memory fence when writing multithreaded C++11: synchronization is built into mutexes/atomics and they handle any necessary fences for you. (Caveat: you are on your own if you use relaxed atomics.)