What is wrong with my Thread ultilizando Synchronized - Java

Asked

Viewed 646 times

0

I started to study tread I saw some examples of java7 and java8 ultilizando lambda, I arrived in part to ultiliza the Synchronized that and to leave kind a wait list of threads where the next one is executed after a finished, I’m testing but I’m not able to run multithreading what I’m doing wrong? the output of the code should be first the T1 then the T2 and finally the T3 but it numca follows the result of when finish a go to the next.

    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();

        }

    }

2 answers

2


You have created an instant sync, since your method imprimirValores() It’s a method of instantiation. Thus, synchronization will work only for objects or methods of that instance that is accessing the synchronized method.

In his method main() you have created 3 threads and each of them with a different instance. So, the method imprimirValores() will not sync 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, you would have to have a single instance that calls 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 only have a single instance accessing the synchronized method, so the synchronization will work. But it can happen that there is no order in which thread will be 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.

  • I thought your answer was flawed in the diversity of solution to the problem, so I made the counterpoint focusing only on this point. Otherwise, she is very good.

  • Thank you test here and ran the book I was reading had almost nothing explanation just talked to use the word Synchronized

1

I won’t stay long because I think reply from @romarcio explains very well. I would just like to leave other alternatives.

Class method

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

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

If by chance you needed to access some object information and even if you insisted on being a class method, 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, object properties are accessible through the parameter selfObj.

Class lock object

Another easy and simple alternative is the existence of an object on which one can make the desired lock. This object needs to be unique to every lock it serves. As we want to serve as lock here the method in every call, independent of instance, I will define that the locking object is a static field of mainThread, because this is your most obvious place.

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 block synchronized allows you to lock on an object, so this same lock can be used at several points of your code.

I used the object of type Lock by purism. If I’m not mistaken Java allows using any object as being pivot of synchronized.

  • 1

    Thank you, there really is a diversity in the solution, nor had seen this function of the lock (Lock).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.