Click here to Skip to main content
15,395,257 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am oversimplifying for the sake of clarity. Hoping someone has come across this kind of weird behavior.


I have two threads that each contain loops going very fast, Thread1 one updates a series of a variables, and Thread2 has a series of ifs designed to act on those variable values. Thread2:

C#
if (A & B)
{
    Flag1 = true;
}

if ((Flag1==true) && foobar1)
{
    Flag1 = false;
    // Do something;
}


The really weird behavior is that Flag1 is definitely not behaving correctly. It gets set to true when the variables in the Thread1 do not warrant that. What's more, using timers it seems that there is a kind of time lag. For example, the calculated elapsed time (using timer) is much smaller than the elapsed time indicated by the debugger. I think this might have something to do with it (in addition to my lack of knowledge). Help!

What I have tried:

I have tried tracking various variables in Thread1 to verify the erroneous behavior.
Posted
Updated 24-Jun-22 5:33am
v3
Comments
Graeme_Grant 24-Jun-22 10:52am
   
I'm not sure what you are doing or why but I don't like the design.

The issue that you have is that you're not doing threadsafe operations.

I think you need to be moving your shared flags into a thread safe operation using the likes of Interlocked.

See this docs on the Interlock Class
Interlocked Class (System.Threading) | Microsoft Docs[^]
   
Comments
Graeme_Grant 24-Jun-22 11:25am
   
It's a bit more involved than just interlocking variables.
Threading isn't a "magic bullet": it's complicated, particularly when you try to get two threads operating on the same data.

Think about it for a moment: each thread runs on a separate core, each with it's own processor and (at least) L1 instruction and data caches. And by design, they don't know about each other. Combine that with register optimization in the JIT compiled code, and it's unlikely that they share any "real" data at all!

To make life even more fun, a simple instruction in C# like
C#
i++;
is not atomic in machine code: it may be a fetch of i as one machine instruction, an increment as a second, and a store as a third. And since cores are independant, even if a value is genuinely stored in no cached memory there is no guarantee that the change will be done correctly because two cores could be reading it at the same time, changing it at the same time, or storing it at the same time - and the last one to execute wins the result!

So when you have a tight loop operating with minimal data, the chances are that it's all working in registers or cache inside the running core, and any changes one thread makes to a variable aren't reflected back to the actual memory until the thread is p paused by OS to free up the core for other threads in the system.

When this happens, your data is called "not thread safe" and very odd, unpredictable, and even intermittent effects can be seen.

To make it thread safe, you have to "lock" the data so other threads can't access it, do what you need with it, then unlock it again each time you want to do anything. And that means the other threads are paused waiting for you to release the lock, because they have to do exactly the same thing each time!
And that raises it's own problems if you aren't careful: deadlocks, where each thread is paused waiting for a lock the other has taken for example; ora massive slowdown in processing speed because locking adds it's own overhead and if threads are constantly waiting for other thread to finish with something, it can get slower than a single-threaded app!

And your design? That's not thread safe, not even close. And making it thread safe is going to take a lot of sitting down and thinking ... once you have finished researching thread safety which is going to take a while as well!
   
Comments
Admin BTA 24-Jun-22 12:43pm
   
In my naivete I thought if I just made the variables that are modified public static, then it should be OK? In my design only one of the threads is actually operating on the variables and the other thread is only "reading" the variables, so I thought by doing this separating there wouldnt be any "signal interference" so to speak. But from what I am understanding, even "reading" the variables in the second thread can be a problem. I'll look into thread safe stuff and try to change the design. Big thanks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900