0

I wrote a SharedObject class which has two methods to increment a variable. The expected result is 200000 but it shows much less than that. I thought the synchronized block will acquire lock on the cnt variable and thus no two threads can modify or access it but it's not happening. Why is it so?

public class Main {
    public static void main(String[] args) throws InterruptedException {
        SharedObject sharedObject = new SharedObject();
        Thread producer = new Thread(new Runnable() {
            @Override
            public void run() {
                sharedObject.produce();
            }
        });
        Thread consumer = new Thread(new Runnable() {
            @Override
            public void run() {
                sharedObject.consume();
            }
        });
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
        System.out.println(sharedObject.cnt);
    }
    static class SharedObject {
        Integer cnt = 0;
        void produce() {
            for(int i=0; i<100000; i++) {
                synchronized (cnt) {
                    cnt++;
                }
            }
        }
        void consume() {
            for(int i=0; i<100000; i++) {
                synchronized (cnt) {
                    cnt++;
                }
            }
        }
    }
}
  • Try defining `cnt` as `final`, and you should see the problem. – Turing85 Aug 05 '23 at 06:49
  • 1
    As an aside: for this concrete problem, I recommend using [`AtomicInteger` (`docs.oracle.com`)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html) instead of `Integer`. This will eliminate the need to use `synchronized`. – Turing85 Aug 05 '23 at 06:51
  • how can i modify the **cnt** variable if it is declared as final? @Turing85 – madina11906036 Aug 05 '23 at 06:54
  • 1
    There seems to be a misunderstanding. You cannot modify `Integer`-instances; they are immutable. – Turing85 Aug 05 '23 at 06:55
  • 1
    Locks are acquired on objects, not variables. When the value of `cnt` changes, that causes different threads to acquire different locks. – Tim Moore Aug 05 '23 at 07:03
  • I replace **Integer cnt = 0** with **MyInt cnt = new MyInt();** adding static class MyInt {int val = 0;} and then it works – madina11906036 Aug 05 '23 at 07:04
  • Understood. Tnx @Turing85 – madina11906036 Aug 05 '23 at 07:07

0 Answers0