Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread-safe class in Java by means of synchronized blocks

Tags:

Let's say we have very simple Java class MyClass.

public class MyClass {
   private int number;

    public MyClass(int number) {
        this.number = number;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}

There are three ways to construct thread-safe Java class which has some state:

  1. Make it truly immutable

    public class MyClass {
       private final int number;
    
       public MyClass(int number) {
        this.number = number;
       }
    
       public int getNumber() {
        return number;
       }
    
    }
    
  2. Make field number volatile.

    public class MyClass {
       private volatile int number;
    
       public MyClass(int number) {
        this.number = number;
       }
    
       public int getNumber() {
           return number;
       }
    
       public void setNumber(int number) {
           this.number = number;
       }
    }
    
  3. Use a synchronized block. Classic version of this approach described in Chapter 4.3.5 of Java Concurrency in practice. And the funny thing about that it has an error in the example which is mentioned in a errata for this book.

    public class MyClass {
       private int number;
    
       public MyClass(int number) {
           setNumber(number);
       }
    
       public synchronized int getNumber() {
           return number;
       }
    
       public synchronized void setNumber(int number) {
           this.number = number;
       }
    }
    

There is one more fact that should be added to the context of discussion. In a multhithreaded environment JVM is free to reorder instructions outside of synchronized block preserving a logical sequence and happens-before relationships specified by JVM. It may cause publishing object which is not properly constructed yet to another thread.

I've got a couple of questions regarding the third case.

  1. Will it be equivalent to a following piece of code:

    public class MyClass {
       private int number;
    
       public MyClass(int number) {
           synchronized (this){
               this.number = number;
           }
       }
    
       public synchronized int getNumber() {
           return number;
       }
    
       public synchronized void setNumber(int number) {
           this.number = number;
       }
    }
    
  2. Will a reordering be prevented in the third case or it possible for JVM to reorder intstructions and therefore publish object with default value in field number?

  3. If an answer for the second question is yes than I have one more question.

     public class MyClass {
       private int number;
    
       public MyClass(int number) {
           synchronized (new Object()){
               this.number = number;
           }
       }
    
       public synchronized int getNumber() {
           return number;
       }
    
       public synchronized void setNumber(int number) {
           this.number = number;
       }
    }
    

This strange-looking synchronized (new Object()) is supposed to prevent reordering effect. Will it work?

Just to be clear, all these examples don't have any practical applications. I'm just curious about nuances of multithreading.

like image 346
wax Avatar asked Mar 08 '12 17:03

wax


People also ask

Is synchronized thread-safe in Java?

synchronized keyword is one of the way to achieve 'thread safe'. But Remember:Actually while multiple threads tries to access synchronized method they follow the order so becomes safe to access.

Is thread-safe means synchronized?

To make it thread safe then, you have to force person 1 to wait for person 2 to complete their task before allowing person 1 to edit the document. Synchronized means that in a multiple threaded environment, a Synchronized object does not let two threads access a method/block of code at the same time.

Which collection class is a synchronized one thread-safe?

The only two legacy collections are thread-safe: Vector and Hashtable.

Which of the following is synchronized which is thread-safe?

Synchronised in the sense of collection framework is thread-safety. Here Vector will providing thread-safety. This way it makes the use of vector safe.


1 Answers

synchronized(new Object()) will do nothing, since synchronization is only on the object you synchronize on. So if thread A synchronizes on oneObject, and thread B synchronizes on anotherObject, there is no happens-before between them. Since we can know for a fact that no other thread will ever synchronize on the new Object() you create there, this won't establish a happens-before between any other thread.

Regarding your synchronzied in the constructor, if your object is safely published to another thread, you don't need it; and if it's not, you're probably in a mess of trouble as it is. I asked this question on the concurrency-interest list a bit ago, and an interesting thread resulted. See in particular this email, which points out that even with your constructor synchronized, in the absence of safe publication another thread could see default values in your fields, and this email which (imho) ties the whole thing together.

like image 183
yshavit Avatar answered Dec 14 '22 00:12

yshavit