How to insure variables are stored in memory before another thread reads them

UPDATE . I asked this question in a different form (see below), and it closed in order to be unconstructive. It’s a kind of shame, since the answers exactly related to what I asked (and solved my problem), but I am new here, so I will definitely try to make it more constructive again.

I work in VC ++ under Windows 7. My multi-threaded program assigns values ​​to variables in one thread, and then sends a signal through an event object to another thread, which is blocked, waiting for this signal. Due to things like the optimization provided by the compiler, there is no guarantee that the data assigned to a variable by one thread will actually be available to another thread, even if you are sure (via the locking mechanism) that the other thread will not try to access until when the data was assigned to a variable. For example, the value may be in the CPU register, remaining there until this register is needed for something else. This avoids unnecessary memory loads if this value is needed again shortly after it was placed in this register. Unfortunately, that meansthat the corresponding place in memory continues to hold the last value that it held until the new value was assigned. Thus, when another thread is unlocked and accesses the memory containing the value of the variable, it will receive the old value, and not the last one that was assigned last.

The question arises: how does one Windows thread apply storage to the memory of the values ​​it assigns to the variables, so that another thread will necessarily get access to them later? There may be several answers, but the one that was asked before this question was closed, which seemed to be the best fit for what I needed, was to use a "memory pick", which was the programming construct about which I have not heard before. After a fence is detected, pending writes to memory are guaranteed to complete. (This, if the fence is a “records” fence, can be made to read from memory using the “read” fence, and both can be read / write with the “fence.” Windows makes all three available quite easily in a VC ++ program).

, Windows ( " " ) , ( , MSDN).

, , ( - ), , . , , , , . ( , , - , , , .)


?

volatile, . , , . , stackoverflow, , , :

, A B, Visual ++. B , A. A . A B, , A. , , A, , CPU.

, B, , A, , A?

+3
4

x86 .

(, boost:: mutex), , / (Memory Barriers @MSDN), , .

, .

+3

. , , , .

, : _ReadWriteBarrier() (, , , _WriteBarrier ), , .

, , , C/++ volatile - volatile . - .

+1

: " - ". : ", ", , , . , .

, :

1) , . , .

2) - . /, , . , A B, "", "" "" B.

3) , ZMQ. , ( ) , . , , .

0

: " , ?" , , , . , , , .

, . , , - , , , . , , , , , .

++ Concurrency , . , , std:: atomic memory. :

std::atomic<bool> signal(false);
std::atomic<int> i(0);

-- thread 1 --
i.store(100,std::memory_order_relaxed);
signal.store(true,std::memory_order_release);

-- thread 2 --
while(!signal.load(std::memory_order_acquire));
assert(i.load(std::memory_order_relaxed) == 100);

, , memory_order_release, , memory_order_acquire, , . , .

, , .

-- thread 1 --
i.store(100,std::memory_order_relaxed);
signal.store(true,std::memory_order_relaxed);

-- thread 2 --
while(!signal.load(std::memory_order_relaxed));
int i2 = i.load(memory_order_relaxed);
// No guarantees about the value loaded from i!

, , .

std::atomic<bool> signal(false);
int i = 0;

-- thread 1 --
i = 100;
signal = true;

-- thread 2 --
while(!signal);
assert(i == 100);
0

All Articles