In-depth analysis: How to understand thread safety more thoroughly?

Source: Internet
Author: User
Tags cas volatile

This is similar to the atomic concept of database transactions, where an operation (which may contain more than one sub-operation) is either fully executed (in effect) or is not executed (none).

A very classic example of atomicity is the issue of bank transfers: A and B, for example, transfer $100,000 to C at the same time. If the transfer operation does not have atomicity, a in the transfer to C, read the balance of C is 200,000, and then add 100,000 of the transfer, calculated that there should be 300,000, but also the future and 300,000 write back to the account of C, at this time B's transfer request came over, B found the balance of C is 200,000, and then add 100,000 and write back Then A's transfer operation technology--write 300,000 back to the balance of C. In this case, the final balance of C is 300,000, not the expected 400,000.

Visibility of

Visibility means that when multiple threads concurrently access a shared variable, one thread shares the modification of the variable and other threads can see it immediately. Visibility issues are a good number of things to ignore or understand wrong.

The CPU's efficiency in reading data from main memory is relatively low, and now there are a few caches in the mainstream computer. When each thread reads a shared variable, the variable is loaded into its corresponding CPU cache, and when the variable is modified, the CPU immediately updates the cache, but does not necessarily write it back to main memory immediately (the time actually written back to main memory is not expected). When other threads (especially those that do not execute on the same CPU) access the variable, the old data is read from the main memory, not the first thread's updated data.

This is an operating system or a hardware-level mechanism, so many application developers often ignore it.

Sequential nature

Sequential means that the order in which the program executes is executed in the order in which the code is executed.

Take the following code as an example

Boolean started = false; Statement 1

Long counter = 0L; Statement 2

counter = 1; Statement 3

started = true; Statement 4

From the code order, the above four statements should be executed sequentially, but in fact the JVM actually executes this code without guaranteeing that they will be executed exactly in this order.

In order to improve the overall execution efficiency of the program, it is possible to optimize the code by adjusting the code order and executing the code in a more efficient order.

In this case, someone is going to have to worry--what, the CPU doesn't execute code in my Code order, how do we make sure we get the results we want? In fact, you can rest assured that the CPU is not guaranteed to execute exactly in code order, but it will ensure that the results of the final execution of the program and the execution of the code sequence are consistent.

How Java solves multi-threaded concurrency problems

How Java guarantees atomicity

Lock and Sync

A common tool for ensuring the atomicity of Java operations is the locking and synchronization methods (or synchronous code blocks). With locks, you can guarantee that only one thread can get the lock at the same time, and that only one thread can execute the code between the request lock and the release lock.

public void Testlock () {

Lock.lock ();

try{

int j = i;

i = j + 1;

} finally {

Lock.unlock ();

}

}

Similar to locks are synchronous methods or synchronized code blocks. When you use a non-static synchronization method, the current instance is locked, and when you use the static synchronization method, the class object is locked, and when you use a static block of code, the object that is enclosed in parentheses after the Synchronized keyword is locked. The following is an example of a synchronous code block

public void Testlock () {

Synchronized (anyobject) {

int j = i;

i = j + 1;

}

}

Regardless of the use of locks or synchronized, the essence is the same, through the lock to achieve the nature of the resource, so that the actual target code segment will only be executed by one thread at the same time, thus guaranteeing the atomicity of the target code segment. This is a method at the expense of performance.

CAS (compare and swap)

The underlying type variable self-increment (i++) is an operation that is often mistaken for an atomic operation by a novice and not actually. The corresponding atomic operation class is provided in Java to implement this operation, and guarantees atomicity, which essentially utilizes the CPU-level CAS directives. Because it is a CPU-level instruction, it costs less than the lock that requires the operating system to participate. Atomicinteger use the following method.

Atomicinteger Atomicinteger = new Atomicinteger ();

for (int b = 0; b < numthreads; b++) {

New Thread ((), {

for (int a = 0; a < iteration; a++) {

Atomicinteger.incrementandget ();

}

})。 Start ();

}

How Java guarantees visibility

Java provides the volatile keyword to ensure visibility. When you use volatile to modify a variable, it guarantees that the modification of the variable is immediately updated to memory, and that the cache of the variable is invalidated in other caches, so that other threads need to read the value from the main memory to get the most recent value.

How Java guarantees sequential

As explained above, when the compiler and the processor reorder the instructions, the result of the reordering is consistent with the execution of the code order, so the reordering process does not affect the execution of the single-threaded program, but it may affect the correctness of concurrent execution of multithreaded programs.

In Java, the order can be guaranteed by means of volatile in a certain program, and also by synchronized and locks.

Synchronized and locks guarantee the principle of order and guarantee atomicity, all by guaranteeing that only one thread executes the target code segment at the same time.

In addition to ensuring the order of the target snippet execution from the application level, the JVM also implicitly guarantees order by being called the Happens-before principle. The order of execution of two operations, as long as they can be deduced through Happens-before, is guaranteed by the JVM, whereas the JVM makes no guarantees about its order, which can be arbitrarily reordered to get high efficiency.

Happens-before principle (the principle of antecedent occurrence)

Delivery rule: If Action 1 precedes action 2 and action 2 precedes action 3, then action 1 will certainly occur before action 3. This rule shows that the happens-before principle is transitive

Locking rule: A unlock operation will certainly occur before the lock operation on the same lock is followed. It's good to understand that locks are only released to be retrieved again.

Volatile variable rule: a volatile-modified write occurs first in the subsequent read operation of the variable

Program Order rules: Within a thread, execute in code order

Thread Start rule: the Start () method of the Thread object first occurs on other actions of this thread

Thread termination principle: All other operations in the thread that occur after the thread's terminating detection

Thread Break rule: The call to the thread interrupt () method occurs first in the acquisition of the interrupt exception

Object Finalization rule: An object construct occurs before its finalize

Volatile application Scenarios

Volatile is suitable for scenarios where there is no need to guarantee atomicity, but need to ensure visibility. A typical usage scenario is to use it to decorate a status token that is used to stop a thread. As shown below

Boolean isrunning = false;

public void Start () {

New Thread ((), {

while (isrunning) {

Someoperation ();

}

})。 Start ();

}

public void Stop () {

IsRunning = false;

}

In this implementation, the loop does not necessarily end immediately, even if other threads set IsRunning to False by calling the Stop () method. The volatile keyword can be used to ensure that the while loop gets the latest state of isrunning in time to stop the loop and end the thread.

Thread safety 100,000 Why

Q: In peacetime, the use of locks and synchronized more, and rarely use volatile, there is no guarantee of visibility? A: Locks and synchronized can guarantee atomicity, and can also guarantee visibility. is achieved by guaranteeing that only one thread executes the target code segment at the same time.

Q: Since locks and synchronized can guarantee atomicity and visibility, why do I need volatile? A: Synchronized and locks require an operating system to arbitrate who gets the lock, the overhead is high, and the volatile cost is much smaller. Therefore, the performance of using volatile is much higher than using locks and synchronized in situations where visibility is only guaranteed.

Q: Since locks and synchronized can guarantee atomicity, why do we need to atomicinteger this class to ensure atomic operation? A: Locks and synchronized require the operating system to arbitrate who gets the lock, the overhead is high, and Atomicinteger is the CPU-level CAS operation to ensure atomicity, the overhead is relatively small. So the purpose of using Atomicinteger is to improve performance.

Q: There is no other way to ensure thread safety answer: Yes. Avoid conditions that cause non-thread-safe-share variables whenever possible. If you can avoid the use of shared variables from the design, you can avoid the occurrence of non-thread-safe, and it is not necessary to solve the problem of atomicity, visibility, and sequencing through lock or synchronized and volatile.

Q: Synchronized can be modified in a non-static way, can also modify the static method, but also modify the code block, what is the difference

A: When synchronized modifies a non-static synchronization method, the lock is the current instance, and when synchronized modifies the static synchronization method, the class object is locked, and when synchronized modifies the static code block, the lock is synchronized The object in parentheses after the keyword.

In-depth analysis: How to understand thread safety more thoroughly?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.