Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Synchronized Threads not working as expected

The following code does not work as I expect it to:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

class Worker implements Runnable {

    public void run() {
        System.out.println("Started.");
        process();

    }
    private Random random = new Random();

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    private static List<Integer> list1 = new ArrayList<Integer>();
    private static List<Integer> list2 = new ArrayList<Integer>();

    public void stageOne() {

        synchronized (lock1) {

            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            list1.add(random.nextInt(100));
        }

    }

    public void stageTwo() {

        synchronized (lock2) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            list2.add(random.nextInt(100));
        }
    }

    public void process() {
        for(int i=0; i<1000; i++) {
            stageOne();
            stageTwo();
        }
    }
    public static void show() {
        System.out.println("List1: " + list1.size());
        System.out.println("List2: " + list2.size());
    }
}

public class JavaTest {

    public static void main(String[] args) {

        long start = System.currentTimeMillis();

        Thread t1 = new Thread(new Worker());
        t1.start();
        Thread t2 = new Thread(new Worker());
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("Completed.");

        long end = System.currentTimeMillis();

        System.out.println("Time taken: " + (end - start));

        Worker.show();
    }

}

When I run this program, I expect list1 and list2 to contain 2000 items each and for the program to take approximately 2000 milliseconds. However, lots of times I get lists less than 2000 items, although it does finish around 2000 milliseconds. Sometimes I even get a ArrayOutOfBounds Exception

Started.
Started.
Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 163
    at java.util.ArrayList.add(ArrayList.java:459)
    at Worker.stageOne(JavaTest.java:34)
    at Worker.process(JavaTest.java:53)
    at Worker.run(JavaTest.java:14)
    at java.lang.Thread.run(Thread.java:748)
Completed.
Time taken: 2217
List1: 1081
List2: 1079

I expect that each the locks in stageOne and stageTwo should stop the threads from interfering with each other. But that does not seem to be the case. What is the problem with this code?

like image 259
Dillydill123 Avatar asked May 11 '17 04:05

Dillydill123


People also ask

Why synchronized method is not working in Java?

So in your case, Thread mt1 acquires lock on Object mt1 and Thread mt2 acquires lock on Object mt2 and they do not block each Other as the two threads are working on two different locks. And when two threads modify a shared variable concurrently(not synchronized way), the result is unpredictable.

How synchronization works internally?

Synchronization is built around an internal entity known as the lock or monitor. Every object has a lock associated with it. By convention, a thread that needs consistent access to an object's fields has to acquire the object's lock before accessing them, and then release the lock when it's done with them.

How to use synchronized keyword in java?

Synchronized blocks in Java are marked with the synchronized keyword. A synchronized block in Java is synchronized on some object. All synchronized blocks synchronize on the same object can only have one thread executing inside them at a time.

When to use synchronized block in java?

A Synchronized block is used to lock an object for any shared resource and the scope of a synchronized block is smaller than the synchronized method.


1 Answers

Your lock objects are not static, so each thread is synchronizing on a different monitor. So the locks are not having any effect at all.

like image 167
Daniel Pryden Avatar answered Oct 26 '22 02:10

Daniel Pryden