Java Thread Miscs

Java Thread Miscs

Multi-thread considerations
1-     Synchronize access to shared mutable data and be ware of insufficient synchronization
When multiple threads share mutable data, each thread that reads or writes the data must perform synchronization.
The synchronized keyword ensures that only a single thread can execute a method or block at one time and prevent an object from being observed in an inconsistent state while it's being modified by another thread, also it ensures one thread's changes would be visible to other threads.
2-     Avoid excessive synchronization
Excessive synchronization can cause reduced performance, deadlock, or even nondeterministic behavior.
Avoid synchronization by other approaches.
1. Don't share mutable data, but share immutable data or a cloned one.
2. Use utilities in java.util.concurrent package, such as AtomicLong
3-     Limit the amount of work within synchronized regions.
Do as little work as possible inside synchronized, If we must perform some time-consuming activity, find a way to move the activity out of the synchronized block.
4-     Prefer executors and tasks to threads
5-     Never use suspend, resume and stop of thread.
6-     For interval timing, always use System.nanoTime
7-     Document thread safety
8-     Avoid multiple locking.
9-     Acquire lock in some consistent well-defined order
volatile keyword
volatile is used to indicate that a variable's value will be modified by different threads.
Declaring a volatile Java variable means: it will not be stored in the thread's local cache. Whenever thread is updating the values, it is updated to the main memory. So, other threads can access the most recently written value.
The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory".
ps: When multiple threads using the same variable, each thread will have its own copy of the local cache for that variable. So, when it's updating the value, it is actually updated in the local cache not in the main variable memory. The other thread which is using the same variable doesn't know anything about the values changed by the another thread.
Avoid busy-wait
busy-wait is the code repeatedly checks a shared object waiting for
something to happen.
API on thread
yield()
Causes the currently executing thread object to temporarily pause and allow other threads to execute.  
Other methods such as suspend, resume and stop are deprecated, and not recommended to use as they are deadlock-prone and not safe.
Thread.stop can result in data corruption.
public final void join() throws InterruptedException
Waits for this thread to die.
public final void join(long millis)
Waits at most millis milliseconds for this thread to die.
Difference between notify and notifyAll
notify wakes a single waiting thread, and notifyAll wakes all waiting threads.
It is safer to use notifyAll.
It will always yield correct results. You may wake some other threads, too, but this won't affect the correctness of your program. These threads will check the condition for which they're waiting and, finding it false, will continue waiting.
Using notifyAll in place of notify protects against accidental or malicious waits by an unrelated thread. Such waits could otherwise “swallow” a critical notification, leaving its intended recipient waiting indefinitely.
As an optimization, you can choose to invoke notify instead of notifyAll.
Timer and ScheduledThreadPoolExecutor
A timer uses only a single thread for task execution, which can hurt timing accuracy in the presence of long-running tasks. If a timer's sole thread throws an uncaught exception, the timer ceases to operate.
A scheduled thread pool executor supports multiple threads and recovers gracefully from tasks that throw unchecked exceptions.
For interval timing, always use System.nanoTime
System.nanoTime is used to time the activity rather than System.currentTimeMillis. For interval
timing, always use System.nanoTime  in preference to System.currentTime-
Millis. System.nanoTime is both more accurate and more precise, and it is not
affected by adjustments to the system's real-time clock.
Improve Performance for Lazy initialization
Under most circumstances, normal initialization is preferable to lazy initialization.
Use lazy initialization holder class idiom on a static field
// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
static FieldType getField() { return FieldHolder.field; }
When the getField method is invoked for the first time, it reads  Field-
Holder.field for the first time, causing the FieldHolder class to get initialized.

A modern VM will synchronize field access only to initialize the class.
Once the class is initialized, the VM will patch the code so that subsequent access to the field does not involve any testing or synchronization.
Use Double-check idiom on an instance field
This idiom avoids the cost of locking when access-
ing the field after it has been initialized.
It is critical that the field be declared volatile
private volatile FieldType field;
    FieldType getField() {
    FieldType result = field;
    if (result == null) { // First check (no locking)
        synchronized(this) {
        result = field; // this is important
        if (result == null) // Second check (with locking)
            field = result = computeFieldValue();
        }
    }
return result;
}
Prefer concurrency utilities to wait and notify
The higher-level utilities in java.util.concurrent fall into three categories: the Executor Framework, concurrent collections; and synchronizers.
The concurrent collections provide high-performance concurrent implementations of standard collection interfaces such as ConcurrentHashMap, ConcurrentSkipListMap, ConcurrentLinkedQueue, ConcurrentSkipListSet.
They combine several primitives into a single atomic operation.
For example, ConcurrentMap extends Map and adds several methods, including putIfAbsent(key, value).
Prefer executors and tasks to threads
It provide thread pool, various kinds of executors.
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(runnable);
executor.shutdown();
In a lightly loaded server, use Executors.newCachedThreadPool.
In a cached thread pool, submitted tasks are not queued but immediately handed off to a thread for execution. If no threads are available, a new one is created.
In a heavily loaded server, use Executors.newFixedThreadPool.
Use executor service provided in java.unit.concurrent package.
The key abstraction is the unit of work, which is called a task. There are two kinds of tasks: Runnable and Callable (which is like Runnable, except that it returns a value).
Deadlock
Deadlock is a situation where two or more threads are blocked forever, waiting for each other. When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. When thread A holds lock L and tries to acquire lock M, but at the same time thread B holds M and tries to acquire L, both threads will wait forever.
How to avoid deadlocks
Acquire lock in some consistent well-defined order
Deadlock usually occurs when multiple threads need the same locks but obtain them in different order.
Shrink synchronized blocks to avoid multiple locking
Do as little work as possible inside synchronized regions.
If you must perform some time-consuming activity, find a way to
move the activity out of the synchronized region.
Never leave control to the client within a synchronized method or block. 
Don't call an alien method from within a synchronized region.
Use Open Calls to Avoiding Deadlock Between Cooperating Objects
Example:
Inconsistent Lock-ordering Deadlocks
public class LeftRightDeadlock {
private final Object left = new Object();
private final Object right = new Object();
public void leftRight() {
synchronized (left) {
synchronized (right) {doSomething();}
}
}
public void rightLeft() {
synchronized (right) {
synchronized (left) {doSomethingElse();}
}
}
}
Dynamic Lock Order Deadlocks
The lock order depends on the order of arguments passed to transferMoney, and these in turn might depend on external inputs. Deadlock can occur if two threads call transferMoney at the same time, one transferring from X to Y, and the other doing the opposite.
public void transferMoney(Account fromAccount,Account toAccount,DollarAmount amountToTransfer) {
synchronized (fromAccount) {
synchronized (toAccount) {
if (fromAccount.hasSufficientBalance(amountToTransfer) {
fromAccount.debit(amountToTransfer);
toAccount.credit(amountToTransfer);
}
}
}}
Consider what happens when thread A executes:
transferMoney(accountOne, accountTwo, amount);
While at the same time, thread B executes:
transferMoney(accountTwo, accountOne, anotherAmount);
Again, the two threads try to acquire the same two locks, but in different orders.
Use an ordering to acquire locks in a fixed sequence
public void transferMoney(Account fromAccount,Account toAccount,DollarAmount amountToTransfer) {
Account firstLock, secondLock;
if (fromAccount.accountNumber() == toAccount.accountNumber())
throw new Exception("Cannot transfer from account to itself");
else if (fromAccount.accountNumber() < toAccount.accountNumber()) {
firstLock = fromAccount; secondLock = toAccount;}
else {
firstLock = toAccount; secondLock = fromAccount;}
synchronized (firstLock) {
synchronized (secondLock) {
if (fromAccount.hasSufficientBalance(amountToTransfer) {
fromAccount.debit(amountToTransfer);
toAccount.credit(amountToTransfer);
}
}}}
Another way to induce an ordering on objects is to use System.identityHashCode, which returns the value that would be returned by Object.hashCode.
Starvation
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads.
Difference between Thread.sleep() and Object.wait()
Thread.sleep
1.       Thread.sleep is static method of Thread class and Thread.sleep would throw InterruptedException when it is awaken by other thread prematurely.
2.       Thread.sleep can be used anywhere in the code to halt the current thread execution for the specified time.
3.       Thread.sleep causes the current thread into Non-Runnable state, but, it doesn't release ownership of the acquired monitors. So, if the current thread is into a synchronized block/method, then no other thread will be able to enter that block/method.
4.       Thread.sleep(n) guarantees to sleep for at least n milliseconds. But it may sleep for considerably more if the system is busy.
5.       If somebody changes the system time, you may sleep for a very long time or no time at all. The behavior is OS and JDK-dependent.
Object.wait
1.     Object.wait is instance method of Object class.
2.     The wait method is used to put the thread aside for up to the specified time. It could wait for much lesser time if it receives a notify() or notifyAll() call.
3.     Object.wait have to be called inside synchronized block, otherwise it would throw IllegalMonitorStateException.
4.     Object.wait causes the current thread into Non-Runnable state, like Thread.sleep, but Object.wait releases the locks before going into Non-Runnable state. This causes the current thread to wait either another thread invokes the 'notify()' method or the 'notifyAll()' method for this object, or a specified amount of time has elapsed.
5.     Using sleep makes your codes non-scalable across hardwares, where a nicely written wait/notify code scales well.

Resources:
Post a Comment

Labels

Java (159) Lucene-Solr (110) Interview (61) All (58) J2SE (53) Algorithm (45) Soft Skills (36) Eclipse (34) Code Example (31) Linux (24) JavaScript (23) Spring (22) Windows (22) Web Development (20) Nutch2 (18) Tools (18) Bugs (17) Debug (16) Defects (14) Text Mining (14) J2EE (13) Network (13) Troubleshooting (12) PowerShell (11) Chrome (9) Design (9) How to (9) Learning code (9) Performance (9) UIMA (9) html (9) Http Client (8) Maven (8) Problem Solving (8) Security (8) bat (8) blogger (8) Big Data (7) Continuous Integration (7) Google (7) Guava (7) JSON (7) ANT (6) Coding Skills (6) Database (6) Scala (6) Shell (6) css (6) Algorithm Series (5) Cache (5) Dynamic Languages (5) IDE (5) Lesson Learned (5) Programmer Skills (5) Tips (5) adsense (5) xml (5) AIX (4) Code Quality (4) GAE (4) Git (4) Good Programming Practices (4) Jackson (4) Memory Usage (4) Miscs (4) OpenNLP (4) Project Managment (4) Spark (4) System Design (4) Testing (4) ads (4) regular-expression (4) Android (3) Apache Spark (3) Become a Better You (3) Concurrency (3) Eclipse RCP (3) English (3) Happy Hacking (3) IBM (3) J2SE Knowledge Series (3) JAX-RS (3) Jetty (3) Restful Web Service (3) Script (3) regex (3) seo (3) .Net (2) Android Studio (2) Apache (2) Apache Procrun (2) Architecture (2) Batch (2) Bit Operation (2) Build (2) Building Scalable Web Sites (2) C# (2) C/C++ (2) CSV (2) Career (2) Cassandra (2) Distributed (2) Fiddler (2) Firefox (2) Google Drive (2) Gson (2) How to Interview (2) Html Parser (2) Http (2) Image Tools (2) JQuery (2) Jersey (2) LDAP (2) Life (2) Logging (2) Python (2) Software Issues (2) Storage (2) Text Search (2) xml parser (2) AOP (1) Application Design (1) AspectJ (1) Chrome DevTools (1) Cloud (1) Codility (1) Data Mining (1) Data Structure (1) ExceptionUtils (1) Exif (1) Feature Request (1) FindBugs (1) Greasemonkey (1) HTML5 (1) Httpd (1) I18N (1) IBM Java Thread Dump Analyzer (1) JDK Source Code (1) JDK8 (1) JMX (1) Lazy Developer (1) Mac (1) Machine Learning (1) Mobile (1) My Plan for 2010 (1) Netbeans (1) Notes (1) Operating System (1) Perl (1) Problems (1) Product Architecture (1) Programming Life (1) Quality (1) Redhat (1) Redis (1) Review (1) RxJava (1) Solutions logs (1) Team Management (1) Thread Dump Analyzer (1) Visualization (1) boilerpipe (1) htm (1) ongoing (1) procrun (1) rss (1)

Popular Posts