1

Im new to multithreading and it's a bit confusing. How could I use the synchronize key to give an output of : 1 a then 2 b ? In other words, I want the first thread to access the static variable x, increment it and then the second thread to start.

public class Test1 extends Thread{
    static int x=0;
    String name;

    Test1(String n){ name=n;}
    public void increment() {
        x=x+1;
        System.out.println(x+" "+ name);
    }

    public void run() {
        this.increment();
    }   
}
public class Main {
    public static void main(String args[]) {
        Test1 a= new Test1("a");
        Test1 b= new Test1("b");
        a.start();
        b.start();
    }
}

2 Answers2

0

You can use synchronized static method (in the increment anyway you are just operating on the static field so why not to make it static?).

public static synchronized void increment() {
    x=x+1;
    System.out.println(x+" "+ name);
}

Such method is synchronizing on the whole class object.

If you really don't want for some reason to make this method static you can explicitely synchronize the critical section on the class object

public void increment() {
    synchronized(Test1.class) {
        x=x+1;
        System.out.println(x+" "+ name);
    }
}
m.antkowicz
  • 13,268
  • 18
  • 37
  • I actually tried this and the compiler gives me 2-2 output for most of the times. – Hussein Jaber Oct 22 '19 at 21:21
  • Thanks it worked! But can you please explain why would the first method given, aka synchronized void increment not work? – Hussein Jaber Oct 22 '19 at 21:28
  • not really sure but maybe the System.out itself is [buffered](https://stackoverflow.com/questions/24401467/is-system-out-buffered-or-unbuffered)? – m.antkowicz Oct 22 '19 at 21:34
  • @HusseinJaber the first method is not "synchronized void increment" but "**static** synchronized void increment". The `static` keyword is the important keyword here. – Erwin Bolwidt Oct 22 '19 at 22:06
0

I'd suggest using an AtomicInteger with a call to incrementAndGet(). This will atomically increment the variable as well as prevent other threads from returning calls to the variable until preceding locks are removed, so your increment method would be:

System.out.println(x.incrementAndGet()+" "+ name);

You can also use a synchronised block as other users have posted, but the drawback of both of the suggestions is that you are sacrificing control of a lock object, since the synchronised keyword on a method is equivalent to:

synchronized (this) { }

And referring to a class object does not keep the object internal to the class.

  • `AtomicInteger` is the solution to a very narrow class of problems. The OP probably should first learn the more general way of protecting data from collisions (i.e., mutexes) . – Solomon Slow Oct 22 '19 at 22:05