Puzzle synchronization with std :: memory_order and three threads

Here is the rule issue std::memory_orderin C ++ 11 when it comes to three threads. Say a single thread producer saves a value and sets a flag. Then another relay flag waits for this flag before setting another flag. Finally, the third thread, the consumer, expects the relay flag , which should signal that it is dataready for the consumer .

Here is a minimal example-style program in the C ++ link ( http://en.cppreference.com/w/cpp/atomic/memory_order ):

#include <thread>
#include <atomic>
#include <cassert>

std::atomic<bool> flag1 = ATOMIC_VAR_INIT(false);
std::atomic<bool> flag2 = ATOMIC_VAR_INIT(false);
int data;

void producer()
{
  data = 42;
  flag1.store(true, std::memory_order_release);
}

void relay_1()
{
  while (!flag1.load(std::memory_order_acquire))
    ;
  flag2.store(true, std::memory_order_release);
}

void relay_2()
{
  while (!flag1.load(std::memory_order_seq_cst))
    ;
  flag2.store(true, std::memory_order_seq_cst);
}

void relay_3()
{
  while (!flag1.load(std::memory_order_acquire))
    ;
  // Does the following line make a difference?
  data = data;
  flag2.store(true, std::memory_order_release);
}

void consumer()
{
  while (!flag2.load(std::memory_order_acquire))
    ;
  assert(data==42);
}

int main()
{
  std::thread a(producer);
  std::thread b(relay_1);
  std::thread c(consumer);
  a.join(); b.join(); c.join();
}

Comments:

  • relay_1() assert . ++ memory_order_acquire ", , , ". , data=42 , flag2. memory_order_release, ", , ". data relay, , data , flag2==True.

  • relay_2(). - , " , std::memory_order_seq_cst". data.

    - relay_2() ?

  • , data, relay_3(). data = data , data flag1 true, relay data, flag2. , .

    . data = data -, ( ) .

    ? ++ 11 std::memory_order?

, . , data , i- (i + 1) - , ≤i.

Edit:

, relay_1() . , . ++ 11 , , - cppreference.com. , . , " " ( ) .

+5
1

, relay_1() , 42 data.

, :

void producer()
{
    /* P */ data = 42;
    /* Q */ flag1.store(true, std::memory_order_release);
}

void relay_1()
{
  while (/* R */ !flag1.load(std::memory_order_acquire))
    ;

  /* S */ flag2.store(true, std::memory_order_release);
}


void consumer()
{
  while (/* T */ !flag2.load(std::memory_order_acquire))
    ;
  /* U */ assert(data==42);
}

A -> B , "Inter-thread B" (++ 11 1.10/11).

, P U, :

  • P Q, R S, T U (1.9/14)
  • Q R, S T (29.3/2)

"inter-thread happens before" (1.10/11):

  • Q -> S, : " B, ... X, A X X B" (Q R R S, Q -> S)

  • S -> U (S T T U, S -> U)

  • Q -> U, Q -> S S -> U ( " B, ... , X X B" )

,

  • P -> U, P Q Q -> U ( " B, ... A , X X B" )

P inter-thread U, P U (1.10/12) P " " U (1.10/13).

relay_3() , data=data .

/ relay_2() , relay_1(), memory_order_seq_cst , memory_order_seq_cst - (. 29.3/1). , . memory_order_seq_cst , , memory_order_seq_cst memory_order_seq_cst, .

, memory_order_acquire memory_order_release , , .

+4

All Articles