|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 7
Long ago, computer scientists invented a term to describe the combined behaviors of multiple threads that lead to inconsistencies.
That term is race condition—the act of each thread racing to complete its critical code section before some other thread enters that same critical code
section. As NeedForSynchronizationDemo demonstrates, threads' execution orders are unpredictable. There is no guarantee that a thread can complete its critical
code section before some other thread enters that section. Hence, we have a race condition, which causes inconsistencies.
To prevent race conditions, each thread must complete its critical code section before another thread enters either the same
critical code section or another related critical code section that manipulates the same shared variables or resources. With
no means of serializing access—that is, allowing access to only one thread at a time —to a critical code section, you can't
prevent race conditions or inconsistencies. Fortunately, Java provides a way to serialize thread access: through its synchronization
mechanism.
Note: Of Java's types, only long integer and double-precision floating-point variables are prone to inconsistencies. Why? A 32-bit JVM typically accesses a 64-bit long integer variable or a 64-bit double-precision floating-point variable in two adjacent 32-bit steps. One thread might complete the first step and then wait while another thread executes both steps. Then, the first thread might awake and complete the second step, producing a variable with a value different from either the first or second thread's value. As a result, if at least one thread can modify either a long integer variable or a double-precision floating-point variable, all threads that read and/or modify that variable must use synchronization to serialize access to the variable.
Java provides a synchronization mechanism for preventing more than one thread from executing code in one or more critical code sections at any point in time. That mechanism bases itself on the concepts of monitors and locks. Think of a monitor as a protective wrapper around a critical code section and a lock as a software entity that a monitor uses to prevent multiple threads from entering the monitor. The idea is this: When a thread wishes to enter a monitor-guarded critical code section, that thread must acquire the lock associated with an object that associates with the monitor. (Each object has its own lock.) If some other thread holds that lock, the JVM forces the requesting thread to wait in a waiting area associated with the monitor/lock. When the thread in the monitor releases the lock, the JVM removes the waiting thread from the monitor's waiting area and allows that thread to acquire the lock and proceed to the monitor's critical code section.
To work with monitors/locks, the JVM provides the monitorenter and monitorexit instructions. Fortunately, you do not need to work at such a low level. Instead, you can use Java's synchronized keyword in the context of the synchronized statement and synchronized methods.