Friday, August 20, 2021

"Final" Keyword, Immutability and Thread Safety in Java

關於Java的Final關鍵字,Immutability與Thread Safety

1. Definition of "Thread safety": Multiple threads will access a shared object coordinately such that unsaved changes made by one thread would not be overwritten by the other.

How to achieve thread safety?


  • Stateless Methods: Stateless methods always produce the same output given the a specific input. It doesn't store states or rely on external states. 
  • Immutability: An immutable class can be created in Java by using private and final on its fields without defining setters.
  • Thread/local fields: So each thread has its own state, and won't share this with other threads.(or shared state with read-only access)
  • Synchronization Collection wrapper: (ex: Collections.synchronizedCollection() method). It means this collection could only be accessed by one thread at a time. Has performance penalty.
  • Concurrent Collection wrapper: (ex: java.util.concurrent.ConcurrentHashMap). Divide collection into data segments and allow multiple-thread access ( where each segment can be only accessed by one thread). Therefore more performant that synchronized collections. Also note that Synchronization and concurrent collections only guarantee the collection itself but not its contents to be thread-safe.
  • Atomic Objects: For example, AtomicInteger and its incrementAndGet() method.
  • Synchronized methods: This is done by using "synchronized" keyword on methods, which allows only one thread access at a time and blocks access on this method from other threads until the accessing thread is done or throws an exception. (releases the lock)
  • Since synchronization is expensive, we have another option to just apply "synchronized" keyword on a specific part of a method. (ex: on a variable)
public class IntrinsicLockOnPrivateFields{

    private int counter = 0;
    private final Object lock = new Object();
    
    public void incrementCounter() {
        synchronized(lock) {
            counter += 1;
        }
    }
    
    // standard getter
}
Since the intrinsic lock is provided by a private field and not visible on outside, this prevents from DoS attack, where attacker acquires the lock and causes deadlock on purpose.

2. Definition of "Immutability": An object is said to be immutable if it cannot be changed once created. Any attempt to modify a fully created immutable object would end up creating a new object. (ex: String class)

3. "Final" Keyword in Java: Makes the by default mutable Java variables immutable.

Note: "Final" forbids the modification of reference to variable, but it doesn't forbid the change of internal values by using public API. (Forbid modification on reference but not value).

Therefore: A finalized list can still be added.

  • Final Classes:

P.s. Final classes cannot be extended, so use it carefully. And final keyword on class doesn't make its fields final or immutable.

  • Final Methods:
cannot be overridden.
  • Final Primitive Variables:
cannot be reassigned.
  • Final Reference Variables:
cannot be reassigned, but the referenced object is not immutable.
ex: Person p = new Person("Tim");
p=new Person("Joe") //Compile error
p.setHeight(180); // this works
  • Final Arguments:
ex: public void getWeight(final int Height) //Height cannot be modified inside the method

No comments:

Post a Comment