How can I avoid threading + optimizer == infinite loop?

In a code review today, I came across the following bit of code (slightly modified for publication):

while (!initialized)
{
  // The thread can start before the constructor has finished initializing the object.
  // Can lead to strange behavior. 
  continue;
}

These are the first few lines of code that run in a new thread. In another thread, as soon as initialization is complete, it sets initializedto true.

I know that the optimizer can turn this into an endless loop, but what's the best way to avoid this?

  • volatile- considered harmful
  • calling a function isInitialized()instead of directly using a variable - will this guarantee a memory barrier? What if the function has been declared inline?

Are there any other options?

Edit:

, , Windows, Linux, Solaris .. Boost.Thread .

+3
5

; โ€‹โ€‹ inline, ( - , , isInitialized() ).

, :

  • initialized ( ++ 0x std::atomic_flag, , )

  • ; .

+5

@Karl - . A , B . B A, .

, psdocode Windows-ish. OS/ .

Windows. :

Thread A:

HANDLE running = CreateEvent(0, TRUE, FALSE, 0);

Thread A, Thread B, :

Thread A:

DWORD thread_b_id = 0;
HANDLE thread_b = CreateThread(0, 0, ThreadBMain, (void*)handle, 0, &thread_b_id);

A :

Thread A:

DWORD rc = WaitForSingleObject(running, INFINITE);
if( rc == WAIT_OBJECT_0 )
{
  // thread B is up & running now...
  // MAGIC HAPPENS
}

Thread B , :

Thread B:

DWORD WINAPI ThreadBMain(void* param)
{
  HANDLE running = (HANDLE)param;
  do_expensive_initialization();
  SetEvent(running); // this will tell Thread A that we're good to go
}
+4

- , ... , .., volatile. , . , , ?

+3

atom_flag, once_flag boost:: once. , .

, , - , , , boost:: once, , . - , , - .

, , .

0

Source: https://habr.com/ru/post/1782809/


All Articles