0

I am learning Java concurrency right now. I came across a piece of code like this:

package pac1;

import java.util.*;
import java.util.concurrent.*;

class A1 {
    public void f() {
        synchronized (this) {
            for (int i = 0; i < 5; i++)
                System.out.println("f()");
        }
    }
}

class B1 {
    public void g() {
        synchronized (this) {
            for (int i = 0; i < 5; i++)
                System.out.println("g()");
        }
    }
}

class C1 {
    public void p() {
        synchronized (this) {
            for (int i = 0; i < 5; i++)
                System.out.println("p()");
        }
    }

}

public class V {
    public static void main(String[] args) {
        A1 a = new A1();
        B1 b = new B1();
        C1 c = new C1();
        new Thread() {
            public void run() {
                a.f();
            }
        }.start();
        new Thread() {
            public void run() {
                c.p();
            }
        }.start();
        b.g();
    }

}

Since this code uses different objects to call synchronized methods, I supposed that it would not prevent them from interfering with each other. However, the result is as follows:

f()
f()
f()
f()
f()
g()
g()
g()
g()
g()
p()
p()
p()
p()
p()

BTW, the result is the same using Lock:

package pac1;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class A {
    Lock lock = new ReentrantLock();

    public void f() {
        lock.lock();
        try {
            for (int i = 0; i < 5; i++)
                System.out.println("f()");
        } finally {
            lock.unlock();
        }
    }
}

class B {
    Lock lock = new ReentrantLock();

    public void g() {
        lock.lock();
        try {
            for (int i = 0; i < 5; i++)
                System.out.println("g()");
        } finally {
            lock.unlock();
        }
    }
}

class C {
    Lock lock = new ReentrantLock();

    public void p() {
        lock.lock();
        try {
            for (int i = 0; i < 5; i++)
                System.out.println("p()");
        } finally {
            lock.unlock();
        }
    }
}

public class Ex16 {

    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        C c = new C();
        new Thread() {
            public void run() {
                a.f();
            }
        }.start();
        new Thread() {
            public void run() {
                c.p();
            }
        }.start();
        b.g();
    }

}
Lucas
  • 167
  • 1
  • 2
  • 9
  • Try printing a lot more things. I suspect that Java finishes running the first thread's method while it's setting up the second one, and then before that one really gets going it's finished running the main method, so you get them all printed in order 1,3,2. I bet if you did 1000 of each they'd be mixed up. – gandaliter Apr 02 '17 at 15:26
  • What makes you think they interfere with each other? Add a call to Thread.sleep(500) at each iteration. – JB Nizet Apr 02 '17 at 15:26

2 Answers2

1

You don't need a lock or synchronized here. Sychronized is used to lock access to shared mutable state. You don't have any shared mutable state to begin with.

You have 3 threads here and nobody can predict the order in which those threads run because of context switching. I don't see a problem.

Avneet Paul
  • 293
  • 1
  • 7
0

Actually the loops simply are not long enough hence allowing threads to finalize in the same order they were launched. In order to make apparent that threads do not interfere you may try one of the following approaches :

  • Make the loop to run longer, e.g. 1000 iterations should be more then enough :

    synchronized (this) { for (int i = 0; i < 1000; i++) System.out.println("f()"); }

  • Suspend the threads within the loops but make sure to have different intervals set for each loop :

    synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println("p()"); try { Thread.sleep(3000); } catch (final InterruptedException ex) { // Swallow } } }

So long story short : These locks actually do not interfere.

Ruben
  • 761
  • 5
  • 9