Professional Documents
Culture Documents
Concurrency N
Concurrency N
Concurrency N
Thread
process
Implement
Competition in threaded environment
Locks and problems with dynamic and simple lock
Dining philosophers
Synchronizers - semaphore, latches, monitors
If synchronization is used to
coordinate access to a variable, it is needed everywhere that variable is accessed.
Further, when using locks to coordinate access to a variable, the same lock must be
used wherever that variable is accessed.
volatile: the variable is volatile and should not be cache. Since it ensures
visibility which applies only to read operations, it will naturally only be usable
on field declarations.
Example: private volatile String notes;
Synchronized: synchronize access to this block of code. It ensures both visibility
and atomicity (or mutual exclusion) so it can be used on blocks of code (also
methods) that have the ability to write or read data, and not on the data itself.
It also performs the visibility function by making sure all the variables declared
inside the block of code is read directly from the main memory at all times instead
of the cache.
Example 1:
public synchronized void takeNotes() {
Example 2:
public void takeNotes() {
sychronized (lock) {
}
}
Question: what if we want to wrap read and write operations on just a single field
variable without using synchronized?
Answer: Atomic variables
Atomic operaion: the smallest operation; an operation that cannot be broken down;
it is also an operation that is performed either entirely or not at all. This means
once a thread is already performing that operation, all others must wait (not at
all) until the thread is through (entirely). If it has to be performed entirely or
not at all, then there is no possibility of there being race conditions whereby
data integrity is lost or the accuracy is compromised because of the existence of
multiple threads performing different stages of the operation interlacingly. An
operation to increment i has to first get the value of i(read operation), increment
it, and update it accordingly(write operation). If after the operation performs the
read operation, another variable performs a write operation changing the variable,
then the integrity of the final result will be compromized.
synchronized keyword basically makes a block of code atomic, as long as none of the
operations performed within the synchronized block is performed elsewhere. All the
operations will either be performed at once and to completion or not at all, and
there is no possibiltity of interlacing errors.
Turning the variable into an atomic variable can also help with this. The classes
contain atomic methods that perform common non-atomic operations, such as
getAndIncrement(). This makes it such that as long as you define your atomic
variable, you won't have to create your own atomic block of code and then try not
to use the same operations elsewhere in a non-atomic way. Instead you just use the
provided atomicized operations to keep your application thread safe.
There are different classes of atomic variables containing atomicized operations
that are commonly required for certain types of variables. For example, the
AtomicInteger class contains the getAndIncrement() atomic method that performs the
common integer operation, get and increment. Others are AtomicLong, AtomicBoolean,
AtomicReference.
The get and set variables also allow writing and reading of data directly to memory
instead of cache.
Monitors: In concurrent programming, a monitor is an object intended to be used
safely by more than one thread.