What is wrong with my thread using synchronized - Java

0

I started to study tread I saw some examples of java7 and java8 using lambda, I came in a part to use the synchronized which is to type a waiting list of threads where the next one and executed after a finish, I am testing but not I'm getting multithreading running what am I doing wrong? the output of the code should be first to T1 then to T2 and finally to T3 but it does not follow the result of when you finish one go to the next one.

    public class mainThread {

        public synchronized void imprimirValores(String numeroThread) {

            for (int i = 0; i < 20; i++)
                System.out.println(numeroThread + " : " + i);

        }

        public static void main(String[] args) {

            new Thread(() -> {

                new mainThread().imprimirValores("T1");

            }).start();

            new Thread(() -> {

                new mainThread().imprimirValores("T2");

            }).start();

            new Thread(() -> {

                new mainThread().imprimirValores("T3");

            }).start();

        }

    }
    
asked by anonymous 15.10.2017 / 00:15

2 answers

2

You have created an instance synchronization, since its imprimirValores() method is an instance method. Therefore, synchronization will only work for objects or methods of that instance that is accessing the synchronized method.

In your main() method you have created 3 threads, each of which has a different instance. Therefore, the imprimirValores() method will not synchronize the 3 threads as a single instance, but rather an instance for each thread and its values will not be printed neatly.

In order for it to work as you want it would have to have a single instance calling the synchronized method, as in the following example:

public static void main(String[] args) {
    MainThread mt = new MainThread();

    new Thread(() -> {

        mt.imprimirValores("T1");

    }).start();

    new Thread(() -> {

        mt.imprimirValores("T2");

    }).start();

    new Thread(() -> {

        mt.imprimirValores("T3");

    }).start();

}

Note that this time we have only one instance accessing the synchronized method, so the synchronization will work. But it may happen that there is no order in which thread is executed first. Sometimes it can be T1, T2, and T3 other times T1, T3, T2 or T2, T1, T3. But the values will be sorted, but the JVM will decide which of the 3 threads it runs first.

    
15.10.2017 / 01:50
1

I'm not going to take too long because I think the @romarcio's answer explains very well. I just want to leave other alternatives.

Class method

Instead of attaching the method to the instance, you could lock the method to the class as a whole. The method itself does not use anything of the instance variable, so it could already be static since its inception:

public static synchronized void imprimirValores(String numeroThread) {
  for (int i = 0; i < 20; i++)
    System.out.println(numeroThread + " : " + i);
}

If you need to access some information of the object and even if you insisted on being a method of the class, you could pass the class as a parameter:

public static synchronized void imprimirValores(mainThread selfObj, String numeroThread) {
  for (int i = 0; i < 20; i++)
    System.out.println(numeroThread + " : " + i);
}

In my example, the properties of the object are accessible through the parameter selfObj .

Class Lock Object

Another easy and simple alternative is the existence of an object on which the desired lock can be made. This object must be unique for every lock it serves. As we want to serve as hangs the method in every call, regardless of instance, I will define that the lock object is a static field of mainThread , as this is its most obvious location.

public class mainThread {
  private static final Lock lck = new Lock();
  public static synchronized void imprimirValores(String numeroThread) {
    synchronized (lck) {
      for (int i = 0; i < 20; i++)
        System.out.println(numeroThread + " : " + i);
    }
  }
  [... o resto do código ...]

The synchronized block allows you to lock an object, so that the lock can be used at several points in your code.

I used the object of type Lock for purism. If I am not mistaken, Java allows you to use any object as a pivot of synchronized .

    
15.10.2017 / 06:31