Thread state values
All new threads start from here. A thread not yet started. It is created, but
start() method not yet called.
A thread during the execution in JVM: running or at least available to run once scheduled.
A thread is waiting to acquire a monitor lock. Then it will be able to execute
A thread that is waiting for another thread (without any timeframe specified).
A thread that is waiting for another thread for a specified period of time.
Thread.join() called with timeout value.
A thread completed execution.
run() method exited or throwed an exception.
Rules of concurrency
Every thread has its own stack, but all threads share the same heap and address space in memory.
- For threads, objects are visible by default - basically, every thread can access any given object by a reference or a copy of this reference. A reference is a pointer to a location in memory (where an object has been located).
- Objects are generally mutable. If a reference variable is final, it cannot be changed by pointing to another object, but the object itself can be still modified. One can create an immutable object, but it is a different story.
- The keyword
synchronizedhelps make code thread safe (or concurrently safe), but it is not enough.
- Thread safety is not only about writing operation on objects: it is also concerns reading objects and data consistency.
- Lock on an
Objectdoes not create locks on objects inside the array.
- Lock on enclosing class does not create lock on inner class.
- Lock on inner class does not create lock on enclosing class.
- Primitive values are not mutable - they cannot be locked, and they do not need to be locked.
- Interface method cannot have
synchronizedkeyword in method declaration.
What is a lock?
A lock (a monitor) is a token. Only one thread a time can have the token.
But when a thread acquires a lock, it does not mean it has exclusive access to the locked object.
It only says: I need access to this
synchronized code. I want to modify the object
and make it temporarily inconsistent using
synchronized block of code.
Briefly, an acquired lock does not prevent from accessing the object. It only stops other threads from getting the same lock / monitor / token.
After the operation, the object backs to consistent state and the thread releases the lock.
Important: locks are coming into play only when given code is marked as
Important: if there exists another thread accessing the same object, but through a non-synchronized method, there is a possibility of concurrent modification or reading inconsistent state.
Optimistic vs pessimistic lock
Both are ways to prevent a lost update to happen.
Optimistic lock: checks whether a value to be updated has not been changed since last read.
Pessimistic lock: explicitly forces other threads to wait until an update is done.
Why some Thread API methods are deprecated?
Thread.stop() immediately stops a thread without returning an object to consistent state.
Thread.suspend() suspends a thread but not releases the lock. When other threads want to acquire the lock, the deadlock occurs.
Thread.resume() creates race condition between deadlocked thread after
Thread.destroy() also creates race condition.
Thread.countStackFrames() is based on
Thread API methods
getAlive() - ID is the same
long for the lifetime of a thread; the rest is obvious
setName() - good practice to name a thread - easier debugging
setPriority(int newPriority) - from 1 (lowest) to 10 (highest), priorities are managed by the scheduler
according to various strategies, probably there is no way to control it.
start() creates a new thread and
run() is the entry point
join() waits for given thread to die