Saturday, July 20, 2024

Multithreading

How do you detect a deadlock in a running Java program?

  • We can use Jconsole to check for Deadlock which comes with JDK. There are also other tools like J visual and flight recorder. They provide inside of our project like all objects that are created all what all deadlocks are happening. We can observe this information and prevent deadlock.
How can we implement JWT token?
  • JWT or JSON Web Token Is an open Internet standard for sharing information Between Two parties.
  • It comprises of a string separated by two periods “.”. These periods break up the JWT into three segments-Header, Payload and Signature.
  • The General form of a JWT is header.payload.signature.
  • Header
    • The first part of the token, the header is a JSON Object containing two properties, the type of token which is JWT and the algorithm used for signing.
  • Payload
    • The second part of the token, the payload contains the data or “claims”, Which you wish to transfer using the JWT. There are some defined claims such as
      • sub- Subject of the token
      • iss- Issue’s of the token.
      • exp- Expiration time of token
      • awd- Audience of token.
  • Signature
    • The signature is created by taking the encoding strings of the first two parts and passing it to the signing algorithm along with your secret.
  • We can provide above implementation in a class, which extends Spring web MVC Adapter and overrides, the configure method. Nowadays, we create a bean of SecurityFilterChain Inside a class annotated by @Configuration.
What is the difference between Hash-map, Synchronized HashMap, concurrent Hash-map, Hash Table?

  • Hash-map
    • Hash map create a 16 bucket internally
    • Each bucket internally uses one linked list
      • Consist of a node Which includes key, value, hash, next
    • Hash-map is not synchronized by default. 
    • Multiple threads can read and write at same time.
    • Not thread safe
    • Can have one Null key and multiple Null values.
  • Hash-table
    • Thread safe
    • Slow performance
    • NULL key and values are not allowed.
    • Provides lock at object level.
  • Synchronized map
    • Thread Safe
    • Only one thread can access a map at a time.
    • Provides lock at object level
    • Slow performance
    • Null key and multiple Null values are allowed
    • Concurrency level cannot be set for better optimization.
  • Concurrent Hash Map
    • Thread Safe
    • Fast performance
    • NULL key and values are not allowed. 
      • If we try to add we get NULL  pointer exception.
    • Introduced in JDK 1.5.
    • Provides a concurrent version of the standard Hashmap.
    • Object is divided into 16 segments (0–15) by default.
    • Depending upon the level of concurrency required the concurrent Hashmap is internally divided into segments.
    • Lock is applied only on write operation.
    • Segment level based locking.
    • Lock is not applied when reading from a segment.
    • Does not throw any Concurrent Modification Exception.
    • Multiple threads cannot write in the same segment.
      • Thread acquires a lock on segment in put() operation and at the time only one thread can write in that segment.
    • Two threads are allowed to write concurrently in different segments.
    • Thread doesn’t acquire a lock on segment in get() operation and any number of threads can read from the same segment.
    • If one thread Is writing in a segment, another thread can read from that segment but in this case last updated value will be seen by the reading thread.
    • Concurrent hash map in Java is a thread safe hash map As it allows only one thread to access the hash map’s locked portion At a time.
    • When you have multiple threads and they access same HashMap, Use concurrent hash map to provide lock only on certain part of map.

What is the difference between identity and concurrent Hashmap?

ConcurrentHashMap uses very sophisticated techniques to reduce the need for synchronisation and allow parallel read access by multiple threads without synchronisation and, more importantly, provides an Iterator that requires no synchronisation and even allows the Map to be modified during iteration.In this class put and remove method are synchronised but not get method.
It implements ConcurrentMap as well as Serializable interface.

IdentityHashMap implements Map, Serializable and Clonable interfaces and extends AbstractMap class.It mandates the use of the "=="  when comparing objects.

Constructors
  • IdentityHashMap(): Constructs a new, empty identity hash map with a default expected maximum size.
  • IdentityHashMap(int expectedMaxSize): Constructs a new, empty map with the specified expected maximum size.
  • IdentityHashMap(Map m): Constructs a new identity hash map containing the keys-value mappings in the specified map.
Methods
  • clear() – Removes all of the mappings from this map.
  • clone() – Returns a shallow copy of this identity hash map: the keys and values themselves are not cloned.
  • containsKey(Object key) – Returns true if this map contains a mapping for the specified key.
  • containsValue(Object value) – Returns true if this map maps one or more keys to the specified value.
  • entrySet() – Returns a Set view of the mappings contained in this map.
  • equals(Object o) – Compares the specified object with this map for equality.
  • get(Object key) – Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
  • hashCode() – Returns the hash code value for this map.
  • isEmpty() – Returns true if this map contains no key-value mappings.
  • keySet() – Returns a Set view of the keys contained in this map.
  • put(K key, V value) – Associates the specified value with the specified key in this map.
  • putAll(Map m) – Copies all of the mappings from the specified map to this map.
  • remove(Object key) – Removes the mapping for a key from this weak hash map if it is present.
  • size() – Returns the number of key-value mappings in this map.
  • values() – Returns a Collection view of the values contained in this map.
How does a fork join executor pool works?
  • Introduced in Java, seven for enhancing parallel programming
  • Based on forking and joining
    • Forking
      • Dividing in sub tasks
    • Joining
      • Combining the result
  • Used for recursive tasks.
  • Based on work, steal algorithm.
    • If a thread becomes available after finishing its assigned tasks and the shared queue is also empty, then it gives the task from the end of the queue of other busy threads.
  • A fork join Executor pool works in parallel stream.
  • It is used by streams
  • Fork join model deals with tasks that produce their own sub tasks
  • It is optimised for problem where tasks can produce more sub tasks.
  • All sub tasks can run parallel all at once on different CPU cores.
  • All the sub tasks are aggregated or joined together to get the final result of main task.
  • Forking Split the tasks into multiple sub tasks.
  • Results of all the sub tasks are joined together into final result.
    • Hence, it is called a fork join model.
  • Folk joint pool has per thread queueing and work stealing strategy.
  • Each head has its own double ended Queue or dequeue Of sub tasks
    • There is no blocking, unless during stealing
    • Easier to schedule
  • Work stealing by a thread is done from other end of the queue.
  • Sub tasks are produced by a thread itself
  • For folk join pool to be effective
    • Code Should avoid synchronisation
    • Should not have shared variables across the tasks.
    • Do not perform blocking IO operations
    • Are pure functions
    • Are Isolated
  • Fork join pools are used in
    • Sorting
    • Matrix multiplication
    • Best move finder for a game
    • Tree Traversal.
  • Uses the implementations of RecursiveTask Abstract class.
How can we avoid dead locks?
  • Synchronise only parts that need to be synchronised.
  • Read operation may not require synchronisation
What is the difference between synchronisation using intrinsic locks and synchronisation using explicit locking(Using lock and Condition)?
  • In Intrinsic Synchronisation it is not possible to interrupt a thread, waiting to acquire a lock, or attempt to acquire a lock without being willing to wait for it forever. In Explicit locking using lock and condition provides option for timed, polled, or interruptible locks Helping Avoid probabilistic Deadlock.
  • In Intrinsic synchronisation responsibility of releasing a lock is handled by JVM, even in case of exception. In explicit locking Lock has to be released manually in a finally block. Once we have modified the protected state.
  • In Intrinsic synchronisation When multiple locks are acquired, they must be released in the same order, and all locks must be released in the same scope in which they were acquired. In explicit locking, we have the ability to implement non-block structure, locking. Lock doesn’t have to be released in the same block of code, unlike synchronise block. 
  • In Intrinsic Synchronisation Choice of fairness to check the lock acquisition is not supported. Explicit synchronisation offer the choice of fairness to the lock Acquisition when multiple threads try to acquire the Shared lock setting fairness flag to true.
  • Intrinsic lock is Available from initial version of Java. Explicit locking is available from JDK 1.5 onwards.
What Is the difference between Synchronised methods and Locks?
  • Synchronised blocks must be contained within a single method. Lock.lock And lock.unlock can be called from defined methods.
  • Lock.lock and lock.unlock Provides the same visibility and happens before guarantee as entering and exiting a synchronised block.
  • Synchronise blocks are always Renterent. Lock can decide not to be.
  • Synchronised blocks do not guarantee fairness. Locks guarantee.
What is synchronisation problem in multithreading And how it can be resolved?
  • We have two threads which read and update a variable through a couple of statements, for example, i++.
  • It may be possible that thread one reads first Then thread 2 reads, The same variable And then thread, one increments the read value, And then thread 2 increment the old read value. This is called as synchronisation problem.
  • So a series of operations(read and write) Are not synchronised between threads, even if the variable is volatile.
    • Read operation of Thread 1 Is followed by Read operation of Thread 2 and Then write operation by thread one Is followed by write operation of Thread 2.
  • It occurs only when we have compound operations and not atomic operations.
  • To solve this problem, we use a synchronised block so that only one thread is allowed to perform operations.
    • Only one thread is allowed to read and increment the value at a time.
  • Another way to solve this problem is to use an atomic integer. In an atomic integer, we have a single method which does this compound operation for us.
    • Instead of incrementing using plus plus we can use value.increment()
      • Even if we do not use synchronised block, it and shows that operation operations are done atomically.
    • Other methods are
      • IncrementAndGet
      • DecrementAndGet
      • AddAndGet(int delta)
      • CompareAndSet(int expectedValue, int NewValue)
    • Atomic integer, atomic Long are used in counters
    • Atomic reference is used in caches(building a new cache) in Background and replacing atomically.
      • Used by some internal classes.
    • Non-blocking classes
What is visibility problem in multithreading and how it can be solved?
  • Volatile is used to counter the visibility problem.
  • Volatile is used in flags.
  • Volatile keyword is used when we want to perform an operation in main memory.
    • It is not stable.
    • Threads can easily change the value
  • The threads, which are used the volatile members Always get updated value as they share the variable.
  • Volatile keyword is kept in the shared cache Of two threads.
  • Since the updated value is not visible to New thread It is called as a visibility problem.
What is atomic concept?
  • Atomic concept is used to solve the parallel synchronisation problems, for an object.
  • Atomic classes work on compare and swap based algorithm.
  • This algorithm does not apply any synchronisation mechanism, but uses volatile values.
  • They use optimistic, locking mechanism instead of passive, locking.
What is the difference between Runnable and Callable interface?
  • For implementing a task, which it returns value, we implement callable interface.
  • If our task does not returns any value, then we use runnable interface.
In how many ways we can create a thread in Java, which is the preferred way and why?
  • We can extend the thread class Or we can implement the runnable interface. Using runnable is preferred As we have the advantage of extending classes later on.
What is the difference between count down latch and cyclic barrier in Java?
What is the use of interrupt() function in Multi-threading and how do we handle an InterruptedException?
  • In Java, one thread cannot stop other thread.
  • A thread can only request the other thread to stop.
  • The request is made in the form of an interruption.
  • Calling the interrupt method on an instance of a Thread sets the interrupt status state as true on the instance.
  • As soon as thread is interrupted any operation on the thread responds by throwing the Interrupted Exception
  • This exception if not handled lets the thread execute further.
  • We can handle this exception either by breaking the loop or by interrupting the current thread by Thread.currentThread().interrupt();
InterruptedSleepingThreadMain.java
 public class InterruptedSleepingThreadMain {  
     /**  
      * @param args  
      * @throws InterruptedException  
      */  
     public static void main(String[] args) throws InterruptedException {  
       InterruptedSleepingThread thread = new InterruptedSleepingThread();  
       thread.start();  
       //Giving 10 seconds to finish the job.  
       Thread.sleep(10000);  
       //Let me interrupt  
       thread.interrupt();  
     }  
 }  
InterruptedSleepingThread.java
 public class InterruptedSleepingThread extends Thread{  
   @Override  
   public void run() {  
     doAPseudoHeavyWeightJob();  
   }  
   private void doAPseudoHeavyWeightJob()  
   {  
     for(int i=0;i<Integer.MAX_VALUE;i++)  
     {  
       System.out.println(i + " " + i*2);  
       if(Thread.currentThread().isInterrupted())   
       {  
         System.out.println("Thread interrupted\n Exiting...");  
         break;  
       }  
       else   
       {  
         sleepBabySleep();  
       }  
     }  
   }  
   protected void sleepBabySleep()   
   {  
     try   
     {  
       Thread.sleep(1000);  
     }   
     catch (InterruptedException e)   
     {  
       Thread.currentThread().interrupt();  
     }  
   }  
 }  
What are the benefits of executor framework?
  • We have to maintain thread status ourselves in general, thread implementation. creation and maintenance of thread is costly operation.
  • In executor framework We already have threads in thread pool.
  • The threads in the third pool are reusable.
  • When a task comes, it is assigned to thread pool automatically.
  • We have a thread pool.
  • From the thread pool We can pick up an ideal thread. It automatically execute the task and pick up another task or release the resources and going to ideal state.
  • We can we reuse threads In executive framework
Where can we use Executor framework?
  • To load data Into cache And it retrieve data from cache We can use Executor service.
  • For Auditing purpose, we can use executor framework. Auditing does not depend on main thread execution. We can create number of executors And provide number of threads.
What is the difference between Executor submit() and Executor execute() method?
  • Submit method is going to give you the future object. Where as execute method is not going to return anything.
  • From the future object, which submit is going to return, we can get result later on once computation is complete By using get() method.
  • Execute is used with threads created from Runnable interface As they don’t return a value. Submit is used with threads created with Callable interface As it returns the value.
How can we avoid deadlock conditions in Java?
  • We can check thread dumps. From thread dump We can check which resource is getting locked, and then from code, we can remove dead locks. from that resource.
  • We can go for jmx , jconsole And check our thread dumps And we can get to know where is the deadlock condition happening.
What is the difference between race condition and deadlock in Java?
  • Deadlock condition happens when we have circular dependencies, that is one thread is trying to Acquire some resource, which is held by another thread, and that thread is trying to acquire the resource held by current thread.
  • Race condition is a thread holding a source Acquired by First thread.
What is lock interface? What is its implementation in which scenarios it is better to use locks over traditional synchronised blocks?
  • Lock interface provides more extensive locking operations, that can be obtained using synchronised methods and blocks. They allow more flexible, structuring, may have quite different properties and may support multiple associated condition objects.
  • Helps in solving Reentrant Lockout Situation where one thread tries to lock object again but can't do so thus it along with other threads keep waiting for object and system is blocked for ever.
  • A Thread can lock an object many times and will have to unlock that many times to totally relese the lock
    • For example In a calculator there may be multiple calculations going on at same time. All these atomic calculations will lock the same same lock and untile all of them release. The lock will not be locked.
    • Useful in cases where sub operations also need to lock the same object and untill all sub opertions of object complete the lock will not be released. 
    • In a synchrozied block same thread cannot hold the lock again.
    • TryLock by deafult does not guarntee fairness add time as below to guarntee fairness
      • lock.tryLock(1000,TimeUnit.MILLISECONDS);
  • The advantages of a lock interface are
    • It is possible to make them fair
      • Longest waiting, thread get served first.
    • It is possible to make a thread respond to interruption while waiting on lock object
      • Using lockinterruptability() object. 
  • It is possible to acquire and release locks in different scopes, and in different orders
    • Using Unlock method.
  • It is possible to try to acquire the lock, but return immediately, or after a timeout, if the lock can’t be acquired.
    • trylock()
    • Trylock(long time,TimeUnit unit).
  • We use lock interface in the renterent lock.
  • We have renterent locks And read/write locks.It provides some fairness parameters, based on the parameters we can lock and unlock. 
  • We do not get these parameters in the synchronised block.
  • If we create a re-enterant lock object then we can use the lock method In there. Re-enterant_lock.lock().
  • So the object will get locked and only one thread will be allowed to access that object.
  • https://github.com/gauravmatta/javacodes/tree/9f44d8c7cd4e6d3602fa5a3fa1fafe57089fd2b7/multithreading/src/com/javaimplant/reentrantlock
  • https://github.com/gauravmatta/javacodes/tree/9f44d8c7cd4e6d3602fa5a3fa1fafe57089fd2b7/multithreading/src/com/javaimplant/readwritelock
How does concurrency API supports explicit locking?
  • Synchronised keyword provides implicit locking.
  • Concurrency API supports various explicit locks by the lock interface.
    • If we want to have more control over the synchronisation or locking/unlocking process, we can make use of the lock interface and its implementation is
      • Reentrant Lock
        • It is a mutual exclusion lock with the same basic behaviour as the implicit monitors access via the synchronise keyword with same extended capabilities as below.
        • If a thread has already acquired a lock, New calls to the lock method, pause their thread until the lock has been released.
        • Only one thread can hold a lock at any given time.
      • Stamped lock
        • They also support read and write locks
        • The locking methods of a stamped lock Retain a scam represent represented by a long value
        • These stamps can be used to either release a lock or to check if the lock is still valid
        • Stamped locks, don’t implement, reenterent characteristics.
        • Each Call to the lock method returns a new stamp and blocks. The third if no lock is available, even if the same third already holds the lock.
        • An optimistic lock supported by stamped lock, which is acquired by calling tryoptimisticread method Which always returns a stamp without blocking the current, no matter if the lock actually is available.
        • Stamp lock can, convert read to write locks by using tryconverttowritelock() method.
      • Read Write lock
        • The read write lock Interface specifies a type of lock that maintains two locks, one for read and another for write access.
        • It is usually safe to read. Mutable variable is currently as long as nobody is writing into this variable.
        • The read lock can be held Simultaneously by multiple threads as long as No threads, hold the write lock.
      • Reentrant Read Write Lock.
What are monitors ?
  • In concurrent programming, a monitor is an object intended to be used safely by one or more threads.
  • The wait and notify Methods in object class, allow us to use any object as a monitor.
  • These characteristics like monitor lock , or intrinsic lock manages synchronisation in Java.
  • All threads calling the same synchronisation method will share the same monitor.
  • All monitors implement re-entrant characteristics
    • Reentrant means That a thread can safely reacquire The same lock multiple times without running into a deadlock.
  • A monitor is a synchronisation mechanism designed in the early 70s
  • A monitor provides three capabilities to concurrent programs
    • Only one thread at a time has a mutually exclusive access to a critical section.
    • Threads when in a monitor can block awaiting certain conditions to become true.
    • A thread can notify one or more threads that conditions they are waiting on, have been satisfied.
  • All objects in Java can be used as built in monitor objects, which support two types of thread Synchronisation.
    • Mutual exclusion, which allows con content access and updates to shared data Without conditions.
      • Every Java object has a single intrinsic lock Associated with it.
      • The intrinsic lock Has entrance Queue Which keeps track off threads that are waiting to get access to critical section.
      • Java out of the box Supports Implicit condition model.
      • JVM Supports entrance queue via Synchronised method keyword.
    • Coordination and shows computations run properly, example in the right order at the right time, under the right conditions, et cetera.
      • Every Java object has one intrinsic condition associated with it.
      • We have a wait queue which has three modules wait(),notify() and notifyAll().
    • These mechanisms implement a variant of Monitor Object Pattern.
      • Intent-Ensure that only one method runs within an object and allows an object’s method  to cooperatively Schedule their execution sequence.
What are semaphores?
  • The concurrency API supports semaphore Locks which grant Exclusive access to variables, but a semaphore maintains whole set of permits.
  • It is useful in case where we have to limit the amount of content access to whole certain parts of the application.

No comments:

Post a Comment