-2

I have 2 unsynchronized threads that modify the global variable. Each thread has 12 iterations. Before the modification command, each stream has a 1 ms delay. As a result, the global variable is equal to 112, which is logical, since the streams modify it simultaneously, BUT if you remove the delay in both streams, then one of them is ahead of the other stream so that the other stream receives the current value of the global variable. Why does this happen when delays are enabled?

#include "stdafx.h" 
#include <windows.h> 
#include <iostream> 
#include <omp.h>
using namespace std;

int global = 100;
HANDLE ht1, ht2; 
DWORD WINAPI ThreadProc1(LPVOID lpParameter ) { 
    int i, j;   
    for (j=1; j <= 12; j++)    {
        i = global;      
        i++;     
        Sleep (1);  //Delay before modifying global variable
        global = i; 
        printf_s( "%4s %4d \n", " 1 th", i );    
    } 
    return 0;  
}
DWORD WINAPI ThreadProc2 (LPVOID lpParameter) { 
    int i, j; 
    for (j=1; j <= 12; j++)    {   
        i = global;      
        i++;     
        Sleep (1);  //Delay before modifying global variable     
        global = i;
        printf_s( "%4s %4d %4d \n", " 2 th", i, j );     
    } 
    return 0; 
} 
int _tmain(int argc, _TCHAR* argv[]) { 
    HANDLE msh[2]; 
    ht1 = CreateThread(NULL, 0, &ThreadProc1, NULL, 0, NULL); 
    ht2 = CreateThread(NULL, 0, &ThreadProc2, NULL, 0, NULL); 
    msh[0] = ht1; 
    msh[1] = ht2;
    WaitForMultipleObjects(2,msh,TRUE, INFINITE);
    return 0; 
} 

delayed result https://i.stack.imgur.com/MYJOm.png

result without delay https://i.stack.imgur.com/klMGc.png

volvo
  • 9
  • 2
  • 7
    Your code has undefined behavior. You cannot share a variable between threads without synchronization. – NathanOliver Apr 09 '19 at 16:43
  • You have no control over when the os schedules your threads, how long it keeps them in the freezer etc. And you *must* synchronise access to shared data. Your program is simply broken with no well defined behaviour. – Jesper Juhl Apr 09 '19 at 16:45
  • 2
    addendum to my comment: You cannot share a variable you write to. If all your threads only read (no thread will do a write) then you don't need synchronization. – NathanOliver Apr 09 '19 at 16:49
  • Please *do not* post images of data (especially not as external links). Post the date as *text*, *in* the question. – Jesper Juhl Apr 09 '19 at 16:53
  • @NathanOliver I specifically turned off synchronization to follow their behavior! And I ask the question WHY with the same delay of the same streams, I get a different result than without this delay. – volvo Apr 09 '19 at 17:11
  • The WHY is because you have undefined behavior. The can do "anything". Making "change" that doesn't change anything can make a difference since the behavior is not defined. – NathanOliver Apr 09 '19 at 17:23
  • @NathanOliver This is nonsense, if it were so, I would not ask this question here. My results are constant, namely: with a delay, the result is always 1, the global variable is eventually equal to 112. And without delay, the result is different and always equal to 124 !! – volvo Apr 09 '19 at 17:31
  • How many times do you suppose [this demonstration](https://www.youtube.com/watch?v=73wMnU7xbwE) worked perfectly before Bill Gates got on stage? Undefined Behaviour is undefined. Maybe you'll get consistent results. Maybe you won't. Maybe you'll get what you expect to see. Maybe you won't. Fix the the undefined behaviour and test again. – user4581301 Apr 09 '19 at 18:50

1 Answers1

2

Based on the thread scheduling of your operating system, when adding a delay, the two threads all execute i = global, the global value is the same in two thread. So it's just an increase of 12. When there is no delay, the code:

i = global;      
i++;     
global = i;

has not been interrupted, equivalent to global++ here. So the result is 100 + 12*2 = 124.

Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • this code still can be interrupted. even `global++` can be interrupted. without use interlocked increment or critical section result can be any from 112 to 124 – RbMm Apr 10 '19 at 08:48
  • Yes, It depends on system behavior. I mean "base on the OP's operation system". – Drake Wu Apr 10 '19 at 08:59
  • Before a thread execute `i = global;`, the other one has increased it. That's the phenomenon on his system. – Drake Wu Apr 10 '19 at 09:07