In the previous section we learned how Java creates threads and starts, and when there is no interaction between threads, program development is straightforward, but if there is interaction between threads, the way in which variables are shared
Interacting, it raises many thread insecurity issues, such as race conditions , data contention , and cache variables .
race condition : When the correctness of the calculation depends on the relative time or the multi-threaded crossover controlled by the dispatcher, the race condition will occur. Here's an example:
if (a = = 10.0) {b = a/2.0;}
If a thread has finished executing if (a = = 10.0), is suddenly stopped by the scheduler, another thread starts executing, and a = 20 is modified, and then the first thread is resumed, B = 10.
This creates a problem.
Data Competition: Data competition refers to two or more threads of more than two concurrent access to the same piece of memory, and at least one of them is to write, and these threads are not reconciled to that block of memory
Access to the domain. When these conditions are met, the order of access is indeterminate. Depending on the order, each run may produce different results
Cache variables: in order to improve performance, the compiler Java Virtual machine and the operating system will coordinate cache variables in registers or in the processor cache, rather than relying on main memory, each thread will have its own
Variable copy. When a thread writes to this variable, it is actually writing its own copy, and other threads are unlikely to see their copy of the variable changed.
Synchronization solves these problems by synchronizing code blocks and synchronizing methods.
Synchronous code block synchronized (lock) {//code required for synchronization}//synchronous method public synchronized void method () {//code to be synchronized}
Use synchronized for synchronization, which is mutually exclusive and visible . The mutex is mutually exclusive for each thread's access to the critical section, which is read from main memory when the thread enters the critical section.
The value of the variable, which, when left, writes the value of the variable to main memory, so he can always see the most recent modification of the shared variable. Synchronization is implemented through the listener , and each Java object is associated with a listener so that the line
Can be unlocked and unlocked by releasing and acquiring a lock on the listener, and a thread can hold only one lock to achieve synchronization. However, although the use of locks can be synchronized, but also face deadlock, live lock , starve
The challenge.
deadlock: thread 1 waits for a thread 2 mutex-held resource, and thread 2 is waiting for a thread 1 to be mutually exclusive, and two threads cannot continue execution
Live Lock: A thread continually retries a failed operation and cannot continue execution
starve: A thread has been delayed by the scheduler to access the resources on which it is executing. Cannot continue execution
The Java language and the JVM do not provide a way to avoid the above problems and error methods, so mainly by our own attention during the programming process, the simplest is to minimize the synchronization method, synchronous block calls between each other
Java also provides a weaker form of synchronization that contains only the visibility, the volatile keyword, and in some cases we only need to focus on the visibility of the code, rather than the mutex, when using synchronized
It does not seem necessary that we should consider using volatile, a volatile tagged property, when the thread accesses him without reading the cached variable's data, but instead reads it from main memory. It is also worth noting that the use of volatile
When modifying a double and a long type, you should avoid doing so on a 32-bit operating system, because double, long is 8 bytes, 64 bits, and its read is divided into two steps on a 32-bit operating system, with 32 bits of data per step,
Volatile guarantees visibility, but does not guarantee the atomicity of operations, so you should pay attention to coding. Using volatile cannot be used in conjunction with final , because final will ensure the security of thread access, and it modifies a
property, the reference to the property cannot be modified, and the reference cannot be cached.
Java Threads----synchronization with concurrent programming practices