Reasons for multithreading:
- I/O bound process
- User Interface thread
- Background task
- Code isolation
- Take advantage of multi-core CPU
Problems caused by improperly implemented thread programming
Race Condition - two threads try to update variable at the same time
Deadlock - two threads cannot proceed because each one is waiting on a lock the other one is holding
Overlock - keep locking when performing other unrelated functions
Types of sync objects:
Any Java object
Object monitor;
synchronized (monitor) {monitor.set();....};
Any Class
synchronized (this.getClass()) {set();....};
Method
synchronized public void func (){...};
wait and notify
synchronize on an object is called having a monitor on the object
synchronized (obj) {
obj.wait();
}
}
synchronized (obj) {
obj.notifyAll();
}
}
concurrent.Semaphore
semaphore.acquire();
semaphore.release();
concurrent.atomic.*
Wrappers for primitive types that support concurrent update
Declare Volatile
Read and write to volatile is ALWAYS synchronized.
Optimistic Locking vs Pessimistic Locking
Optimistic Locking
- Conflict detection, lock first, detect conflict later
- Improve concurrency
- Lock is held only during commit
- Best when conflict is rare and consequence is no big deal
Pessimistic Locking
- Conflict prevention
- Reduce concurrency
- Best when consequence is painful
Process isolation and concurrency
- Process per session
- Process per request - popular webserver implementation
- Thread per request
Deadlock
Method exposed to deadlock
int func() {
++n;
++n;
return n;
}
when executed from multiple threads may not always return an even increment
Concurrent package:
atomic: wrapper classes allowing access as if it is volatile
unlike Java wrapper has nave no hashCode() or compareTo()
lock: reentrant locks, multithread access prioritized by starvation time
blocking queue: insert is blocked until remove is called and vice versa