-2

So I am looking at an IBM Article and I couldn't get my head around with the below statements.

public class Counter {
  private int counter = 0;

  public int  get()      { return counter; }
  public void set(int n) { counter = n; }
  public void increment() {
    set(get() + 1);
  }
}

What happens if two threads try to execute increment() at the same time? The counter might be incremented by 1 or by 2.

My doubts is that if a Thread A executes the above statement for the first time, then get() will return 0 and set increment will set it to 1. Only after the thread A finish executing or goes to sleep, Thread B can start executing ? How come both Thread A and Thread B can execute a piece of code at the same time ? How can counter be incremented by 2 ?

ks55NGMC
  • 1
  • 1
  • "How come both Thread A and Thread B can execute a piece of code at the same time ?" How many cores does your CPU have? How many processors does your computer have? Even with a single core a thread doesn't necessarily get to execute a full method call until it has to allow different code to execute (whether your code, or other code that needs to run inside your machine). – Kayaman Jul 21 '20 at 13:34
  • from this https://stackoverflow.com/questions/19744508/volatile-vs-atomic "Notably, however, an operation that requires more than one read/write -- such as i++, which is equivalent to i = i + 1, which does one read and one write -- is not atomic, since another thread may write to i between the read and the write." – newbie Jul 21 '20 at 13:36
  • my question is - if thread A initialized an object to a variable at **0.01** sec. Then how come thread B can also initialize the same object to a variable at exactly **0.01** sec. What am I missing here ? Since code is nothing but 010101, then if a some thread is executing some memory block at some time, then how come another thread can access and execute the same memory at exactly the same time ? – ks55NGMC Jul 21 '20 at 13:39
  • @ks55NGMC What is it conceptually in your mind that _prevents_ two threads from executing the same thing at the same time? – khelwood Jul 21 '20 at 13:43
  • @ks55NGMC Some of the improper thread interactions are very rare, but that makes them very difficult to debug as well. It is best to fix them before problems occur. – NomadMaker Jul 21 '20 at 14:13
  • @ks55NGMC, It is _not_ possible for two threads to store different values into the same memory location at the same time, but your `Counter#increment()` performs more steps than just storing a value; It _fetches_ a value, then it performs a computation, then it stores the result. See my answer (below) for how that can go wrong in a multi-threaded environment. – Solomon Slow Jul 21 '20 at 15:22
  • Isn't the **entire point** of threads, that they can execute at the same time? Why would you use threads otherwise? – user253751 Jul 21 '20 at 18:46

2 Answers2

0

When a shared resource is modified by 2 or more threads and the access to that resource isn't synchronized, there is no guarantee that either thread will have the same view of the resource and therefor the result of modification could differ due to inconsistent views. This is called interleaving.

To solve this problem, simply use mutual exclusion to ensure that two threads cannot modify the object at the same time by synchronizing access to each of the methods. This includes both the setters and getters.

Jason
  • 5,154
  • 2
  • 12
  • 22
0

How come both Thread A and Thread B can execute a piece of code at the same time?

Because that's the whole point of threads. It's what threads are for: Threads exist so that different "activities" in a program can happen concurrently with each other.

How can counter be incremented by 2?

Isn't that what you want? Don't you want the value of some counter to increase by two if counter.increment() is called two times? What you should not want is for the value of the counter to only increase by one in that case.

Here's one way that can happen. Suppose that counter==3:

Thread A                               Thread B
enters increment()
calls get(), get returns 3             enters increment()
computes new value, 4
                                       calls get(), get returns 3
calls set(4).                          computes new value, 3+1=4
returns from increment()               calls set(4)
                                       returns from increment()

An experienced Java programmer who looks at your Counter class would say that it is not thread safe.

A "Thread safe" class, in a nutshell, is a class that guarantees to behave in certain useful ways, even when its methods are called by different threads at the same time. For example, a thread-safe Counter class would document, and ensure that no matter how many threads call its increment() method at the same time, the end result, after they've all returned, is that the counter value will have increased by an amount equal to the number of calls.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57