Thursday, April 28, 2016

JAVA CONCURRENCY - my notes for Applying Concurrency and Multi-threading to Common Java Patterns

Applying Concurrency and Multi-threading to Common Java Patterns on Pluralsight.com
Author blog (Jose Paumard): http://blog.paumard.org/en/


GOLDEN RULE IN CONCURRENT PROGRAMMING
Never expose to outside the lock object 
you use to synchronize your code!!!



Thread Scheduler is responsible for the time sharing of CPU.

3 Reasons why Scheduler pause the threads:


Race Condition

Lock object has ONE key (monitor) for a threads.
Each synchronized method has a Lock object.
Key of Lock object calls MONITOR (synchronization object)

Three way of Synchronization:
private static synchronized - will implicitly set as CLASS as a MONITOR

public (non-static) synchronized method - will implicitly set INSTANCE as MONITOR

private final Object key = new Object(); - is the best approach to hide synchronization object at all

Synchronization on INSTANCE will not prevent to access in case of DIFFERENT objects

Synchronization on CLASS will give access to only one object at once

Locks Are Reentrant
"When a thread holds the lock, it can enter a block synchronized on the lock it is holding"
It is when two methods has the same one lock object (key)

DEADLOCK
"A deadlock is the situation when the thread T1 holds a key needed by the thread T2, and T2 holds the key needed by T1".

JVM can detect deadlocks, but you nothing can do except to reboot JVM.

public class FirstRunnable {

    public static void main(String[] args) {
        Runnable runnable = () -> {
            System.out.println("I am running in " + Thread.currentThread().getName());
        };

        /*            The result is that two threads are running concurrently:             the current thread (which returns from the call to the start method)             and the other thread (which executes its run method).        */        Thread t = new Thread(runnable);
        t.setName("My thread");
        t.start();
        //t.run(); //NO NO NO!!! this will be run by main thread not "My thread"    }
}

HOW TO STOP THREAD
NO: never use thread.stop() method! It is there now only for a legacy compatibility.

YES: use thread.interrupt(). It will not stop the thread, but it sends the signal to the task is running, telling it that it is time for this task to stop.

Calling thread.interrupt() will make the result of thread.isInterrupted() to be TRUE. If the thread is blocked or waiting, then the corresponding method will throw an InterruptedException.

The interrupted state should constantly be checked:

More About InterruptedException, LinkedBlockedQueue etc

CONSUMER / PRODUCER

Race condition: in example all threads are looking for buffer & count fields at the same time.


Fixing race condition with Lock object like that will create another kind of deadlock (on 'while'):


Add WAIT and NOTIFY to the fix:

THREAD STATES
Thread Scheduler WILL give a time slice for a thread if:
NEW (it is just have been created)
RUNNABLE (after thread.start() is called)
TERMINATED (it is finished task)

Thread Scheduler WILL NOT give a time slice for a thread if:
RUNNABLE : BLOCKED (is waiting for a lock key)
RUNNABLE : WAITING (is parked by a wait() call)
RUNNABLE : TIMED_WAITING (is parked by a sleep(timeout) or wait(timeout))



FROM Thread class : 
public enum State:

/** * Thread state for a runnable thread.  A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */RUNNABLE,

/** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling Object.wait. */BLOCKED,

/** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: Object.wait, Thread.join, LockSupport.park
 * * A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called Object.wait()
 * on an object is waiting for another thread to call * Object.notify() or Object.notifyAll() on * that object. A thread that has called Thread.join()
 * is waiting for a specified thread to terminate. */WAITING,

CPU Architecture

Visibility of variables in memory
A variable is said visible if the writes on it are visible. All the synchronized writes are visible.
Visibility means "a read should return the value set by the last write"

JVM "Happen Before" link

How Happen Before link is set in Java
In separated methods: Either by synchronize block or volatile variable 
In the same method: by the order of LOCs in it

False Sharing
When thread updates variable it marks its cache as "dirty". This dirty cache broadcast "dirty" state to the other cache very the same variable copied (by false sharing). So when the other thread tries to read that variable in its one cache it sees it as "dirty" and start to refresh it value from the main memory. This impacts the performance:



No comments: