WhyJava Bean Template is not thread safe

Joshua Bloch states in Effective Java, 2nd Edition:

An alternative to the telescopes constructor pattern is the JavaBean pattern, in which you call the constructor with the required parameters and then call any additional setters after:

Pizza pizza = new Pizza(12);
pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);

      

The problem is that, since an object is created across multiple calls, it can be in an inconsistent state in part through its construction. It also takes a lot of effort to ensure thread safety.

My question is: - Is over non-thread code safe? Am I missing any basic thing?

Thanks Advance,

Surya

+3


source to share


2 answers


the code you showed us only includes one thread, so the thread safety of this code is debatable.

If multiple threads can see the instance Pizza

, then there are a few things to worry about:

  • Can another thread see the instance Pizza

    before completing its initialization?

  • When another thread sees an instance, will it observe the correct values ​​for the attributes?

The first problem is not about "publishing" links to another stream until you've finished initializing it.

The second can be solved by using an appropriate synchronization mechanism to ensure that the changes are visible. This can be done in several ways. For example:



  • You can declare getters and setters as methods synchronized

    .
  • You can declare (private) variables that contain attribute values ​​as volatile

    .

Note that the JavaBean pattern does not dictate the order in which the beans are built. In your example, you use the no-args constructor and then set the fields using setters. You can also implement a constructor that allows you to pass arguments that give (non-default) initial values ​​for properties.

It also takes a lot of extra effort to ensure thread safety

Not really. In this context, this is a small change to make getters and setters thread safe. For example:

public class Pizza {
     private boolean cheese;

     public synchronized /* added */ void setCheese(boolean cheese) {
         this.cheese = cheese;
     }

     public synchronized /* added */ boolean isCheese() {
         return cheese;
     }
}

      

+3


source


The author says in a textual way:

The JavaBeans pattern eliminates the ability to make a class immutable and requires additional effort on the part of the programmer to ensure thread safety.

I think the author is highlighting the fact that there is no point in proposing methods that prevent the object from being immutable, but can create consistency problems between threads if you are objective to make them immutable: it should never change after creation.

Your question:

Why is Java Bean Pattern not thread safe?

Any class that provides a way to modify a field is not thread safe.
This is true for JavaBeans methods (which usually do not use defensive copy), but it is also true for any mutable class.

Non-thread safe class manipulation is not a problem as long as you use it in a context where you don't have race conditions between threads.
For example, this code is thread safe:

Pizza pizza = new Pizza(12);
pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);

      

because an instance is Pizza

not declared as a variable that is shared (an instance or a static field), but is declared and used in a more limited scope (it might be a method, but it might also be an initializer block). <w>

The builder pattern provides a way to create an immutable and therefore by definition stream-protected object.

For example, using a builder to create Pizza

:

Pizza pizza = new Pizza.Builder().cheese(true).pepperoni(true).bacon(true).build();

      

Only the call build()

creates and returns the object Pizza

.
Previous calls manipulate the object Builder

and return Builder

.
So, if the object is immutable, you don't need to worry about synchronizing these calls:

pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);

      



as this method is not required. Therefore, they cannot be named.


How to Create Thread-Safe JavaBeans

If you are in a context where an instance Pizza

can be shared across multiple threads, these calls should be done in a synchronized manner:

pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);

      



They can be declared as a method synchronized

, and the fields Pizza

can be volatile, but they can't be enough.

Indeed, if a pizza is to change its state according to its own state, or even to another object, we must also synchronize all the logic: perform checks before changing the state Pizza

.

For example, suppose you Pizza

have to add some units of Pepperoni only once:

The code could be:

  if (pizza.isWaitForPepperoni()){
      pizza.addPepperoni(5);
  }

      

These assertions are not atomic and therefore thread safe.

pizza.addPepperoni(5);

can be called by two parallel threads, even if one of the threads has already called pizza.addPepperoni(5);

.

So we need to make sure no other thread calls pizza.addPepperoni(5)

until it should (the pizza will have too many Pepperoni).
For example, by executing a synchronized instance statement Pizza

:

   synchronized(pizza){
      if (pizza.isWaitForPepperoni()){
          pizza.addPepperoni(5);
      }
   }

      

+1


source







All Articles