Reputation: 61
I am trying to understand multithreading and am confused about how the timing of execution of multiple threads causes problems like race conditions. I recently read this in an article: "When you introduce the concept of multithreading, you are opening up the possibility of two Threads accessing/modifying the same Object in memory at the same time." What exactly do we mean by "at the same time"? Does it mean that a memory location can be read by multiple threads at the same instance of time for example, two threads read the value of a variable a at exactly 1.1 second mark? If yes, then does this diagram from Java Concurrency in practice imply that thread B read the value 9 a tad later than thread A? How should I interpret it?
Upvotes: 1
Views: 387
Reputation: 52133
Let me start by saying multithreaded code is complicated and there are a number of different things that can go on when you think in terms of parallelism.
A race condition usually refers to a situation on parallel code where depending on the order of execution of the different parallel execution threads you obtain different results. The "race" refers to the fact that different threads "compete" for share resources and different order into the finishing line produce different results.
The first thing you have to understand is that nowadays, most of the development is done through what's called high level languages like C#, Java, Golang, etc. In those languages one line of code, even if it may appear as a single command to you, it's actually translated into multiple assembler instructions.
In that way, when you do the most simple example of:
value = a + 1;
In reality, under the hood, that gets translated (broadly) into:
With that part understood, you'll see how now when we say two things execute at the same time we mean the higher level abstraction
If you think about those 3 steps I highlighted, it then makes a lot more sense to think in terms of race conditions. If you look back at the image you posted the sequence is as folows:
Final value is 10.
If, however, you change when the context switches happen:
Final Value: 11
Therefore, depending on the order of execution of the threads, you'll get different results. This is what's usually called a race condition.
This is all very simple because this is a simple increment operation. As the code become more complex, so do the nature of the race conditions but it all comes to the fact that what you perceive as a single operation in high level code, it's actually compiled down to several operations in IL or assembler.
Upvotes: 1
Reputation: 270
You should have read a bit more. In simple words, suppose we are using two run methods that are accessing lets say variable x=5.
method A writes the value to say x=10.
Now method B writes it to x=15.
Now if after a while method a wants the value of x, it will get x=15 and no x=10. Thus same value is accessed by both the methods.
Upvotes: 1
Reputation: 562
I will try to be as clear and short as possible.
Let's say you have some variable stored in some part of your memory with adress 0x101010. Let's say this variable is a counter that counts how many times was certain function (X) called. There are two threads (A and B) that call function X. A has called X and 0.0001 ms later B did it as well. Let's say initial value of the counter was 0. Then A has read value zero at time 0s and incremented it at time 0.0002 ms. Thus at time 0.0002 ms value is 1. However, B has read this value at time 0.0001ms (0.0001 < 0.0002). At this time the counter was still zero. and also incremented it to one at time 0.0003 ms. In the end, the counter value is 1, when it should be 2.
Upvotes: 1