java-Concurrency-Thread safety

Source: Internet
Author: User
Tags volatile

The visibility and ordering of multithreading
——— – The communication between multiple threads cannot be communicated to each other, and they can only be communicated through shared variables. JMM Specifies that the JVM has main memory and that the main memory is shared by multiple threads. When the new object is also allocated in the main memory, each thread has its own working memory, the working memory stores a copy of some objects of memory, of course, the size of the working memory of the thread is limited.
When a thread is manipulating an object, the order of execution is as follows:
(1) Copying variables from main memory to current working RAM (read and load)
(2) Execute code, change shared variable value (use and assign)
(3) Refresh main memory related content (store and write)
When a shared variable has a copy in the working memory of multiple threads, if a thread modifies the shared variable, the other thread should be able to see the modified value, which is the problem of multi-threaded visibility.
A thread cannot reference a variable directly from the main memory, and if the thread does not have the variable in its working memory, it copies a copy from the main memory to the working memory, which is read-load, and the thread references the copy when it is finished. When the same thread references the field again, it is possible to retrieve a copy of the variable from main memory (Read-load-use), or it may refer directly to the original copy (use), meaning that the read,load,use order can be determined by the JVM implementation system. A thread cannot assign a value directly to a field in the primary save, it assigns the value to a copy of the variable in the working memory (assign), and when done, the copy of the variable is synchronized to the primary store (Store-write), and as to when the past is synchronized, the system is determined by the JVM. There is this field, The field is assigned to the working memory from the main memory, the process is read-load, and the thread references the variable copy when it is finished, and when the field is repeatedly assigned to the same thread multiple times

    fori=0;i<10;i++)        a++;  

It is possible for a thread to only assign to a copy in working memory, only to the primary store after the last assignment, so the assign,store,weite order can be determined by the JVM implementation system

     Public  class  account {           Private intBalance PublicAccount (intBalance) { This. balance = balance; } Public intGetBalance () {returnBalance } Public voidAddintnum) {balance = balance + num; } Public voidWithdraw (intnum) {balance = Balance-num; } Public Static voidMain (string[] args) throws Interruptedexception {Account account =NewAccount ( +); Thread A =NewThread (NewAddthread (Account, -),"Add"); Thread B =NewThread (NewWithdrawthread (Account, -),"Withdraw");               A.start ();               B.start ();               A.join ();               B.join ();           System.out.println (Account.getbalance ()); }Static  class addthread implements Runnable {Account Account;intAmount PublicAddthread (Account account,intAmount) { This. account = account; This. Amount = Amount; } Public voidRun () { for(inti =0; I <200000;                   i++) {Account.add (amount); }               }           }Static  class withdrawthread implements Runnable {Account Account;intAmount PublicWithdrawthread (Account account,intAmount) { This. account = account; This. Amount = Amount; } Public voidRun () { for(inti =0; I <100000;                   i++) {Account.withdraw (amount); }               }           }       }

The first execution result is 10200, the second execution result is 1060, and the result of each execution is indeterminate, because the order in which the threads are executed is not predictable. This is the root cause of Java synchronization, the Synchronized keyword guarantees that multiple threads are mutually exclusive to the synchronization block, and synchronized as a synchronous means to solve the Java Multi-threading execution order and memory visibility, The volatile keyword solves the problem of multi-threaded memory visibility.

Synchronized keywords

Java uses the Synchronized keyword as one of the guarantee methods for the execution order of multi-threaded concurrency environment. When a piece of code modifies a shared variable, this section of code becomes a mutex or a critical section, in order to ensure the correctness of the shared variable, synchronized indicates the critical section

    publicsynchronizedvoidadd(int num) {            balance = balance + num;       }       publicsynchronizedvoidwithdraw(int num) {            balance = balance - num;       }  

A thread executes the critical section code procedure as follows:
1 Obtaining a Sync lock
2 Empty working memory
3 copy variable copy from main memory to working RAM
4 Calculation of these variables
5 Write a variable from working memory back to main storage
6 Release Lock
It can be seen that synchronized not only guarantees the concurrent order of multithreading, but also ensures the memory visibility of multithreading.

Producer/Consumer Model

The classic thread synchronization model

Import java.util.ArrayList; Import java.util.List; Public classPlate {list<object> eggs =NewArraylist<object> (); PublicSynchronized ObjectGetegg() { while(eggs.size () = =0) {Try{Wait (); }Catch(Interruptedexception e) {}} Object egg = eggs.Get(0); Eggs.clear ();//Clear the plateNotify ();//Wake up a thread from the blocking queue to the ready queueSystem. out. println ("Get the eggs.");returnEgg } PublicSynchronizedvoid Putegg(Object Egg) { while(Eggs.size () >0) {Try{Wait (); }Catch(Interruptedexception e) {}} eggs.add (egg);//Put eggs in the plateNotify ();//Wake up a thread from the blocking queue to the ready queueSystem. out. println ("Put the eggs"); }StaticClass Addthread extends thread{PrivatePlate Plate;PrivateObject egg=NewObject (); Public Addthread(Plate Plate) { This. plate=plate; } Public void Run(){ for(intI=0;i<5; i++) {Plate.putegg (egg); }               }           }StaticClass GetThread extends thread{PrivatePlate Plate; Public GetThread(Plate Plate) { This. plate=plate; } Public void Run(){ for(intI=0;i<5; i++) {Plate.getegg (); }               }           } Public Static void Main(String args[]) {Try{Plate plate=NewPlate (); Thread add=NewThread (NewAddthread (plate)); ThreadGet=NewThread (NewGetThread (plate)); Add.start ();Get. Start (); Add.Join();Get.Join(); }Catch(Interruptedexception e)               {E.printstacktrace (); } System. out. println ("End of Test"); }       }

Declares a plate object to be plate, shared by thread A and thread B, a specializes in eggs, and B specializes in eggs. Assume
At 1, a calls the Plate.putegg method, at which time Eggs.size () is 0, so the egg is successfully placed on the plate, and the Notify () method is executed to wake the locked thread of the blocking queue, at which point the blocking queue has no threads.
2 Another A-thread object calls the Plate.putegg method, at which point Eggs.size () is not 0, and the Wait () method is called, which itself enters the blocking queue of the lock object.
3 At this point, came a B thread object, called the Plate.getegg Method, Eggs.size () not 0, successfully got an egg, also executed the Notify () method, wake-up lock the blocking queue thread, at this time the blocking queue has a thread object, wake up, It goes into the ready queue, and the ready queue is one, so get the lock right away, start putting eggs on the plate, and the plate is empty, so put the eggs to success.
4 assume that the next thread A, repeat 2, assuming that the incoming thread B, repeat 3.
The whole process is guaranteed to put eggs, take eggs, put eggs, take eggs.

volatile keyword

Olatile is a kind of synchronization method provided by Java, but it is a lightweight synchronization, why say, because volatile can only guarantee the multi-threaded memory visibility, does not guarantee the execution of multi-threaded order. And the most thorough synchronization to ensure the order and visibility, such as synchronized. Any variable that is modified by volatile does not copy the copy to the working memory, and any changes are written in memory in time. As a result, changes to Valatile modified variables are immediately visible to all threads, but volatile does not guarantee that changes to variables are ordered.

publicclass VolatileTest{  publicvolatileint a;  publicvoidadd(int count){       a=a+count;  }}

When a Volatiletest object is shared by multiple threads, the value of a is not necessarily correct, because A=a+count contains several steps, at which time the execution of multiple threads is unordered, because there is no mechanism to ensure that the execution of multiple threads is ordered and atomic. The meaning of the volatile existence is that any thread changes to a will be read by other threads immediately, because the direct operation of main memory, there is no thread to the work and main storage synchronization. Therefore, volatile usage scenarios are limited, and in limited cases, volatile variables can be used instead of locks. For the volatile variable to provide ideal thread safety, the following two conditions must be met:
1) The write operation to the variable does not depend on the current value.
2) The variable is not included in the invariant with other variables

publicclass VolatileTest{     publicvolatileint a;     publicvoidsetA(int a){         this.a=a;     }   

In a multithreaded environment where there is no volatile declaration, the final value of a is not necessarily correct, because this.a=a involves assigning a and synchronizing a to main memory, which can be disrupted. If it is declared with volatile, it is equivalent to an atomic operation to read a copy of main memory to working memory and to synchronize a to memory. So in simple terms, volatile is suitable for this scenario: A variable is shared by multiple threads, and the thread assigns it directly to the variable. This is a very simple synchronization scenario where the cost of using volatile is very small.
The working memory of a thread is simply an abstract description of the CPU registers and caches, and the CPU does not always read data from memory when it is calculated, and its data reading order priority is: Register-cache-memory. The thread consumes the CPU, the thread calculates the raw data from the memory, during the calculation, some data may be read frequently, the data is stored in registers and caches, when the thread is calculated, the cached data should be written back to memory when appropriate. When multiple threads read and write some memory data at the same time, there is a multi-threaded concurrency problem, involving three features: atomicity, ordering, visibility. The dynamic memory model is even beyond the scope of the JVM.

JMM

1. Program counter
is a small memory space, and each Java thread has a program counter that holds the instructions that the program executes to the current method, as a line number indicator of the bytecode. Branches, loops, jumps, exception handling, thread replies, and so on. Each thread is privately owned by a counter, stored independently, noting that the counter memory area is the only area that does not stipulate no oom.
2. Line Stacks-Bytecode service
The life cycle, like threads, is thread-private. When each method of a thread is executed, a frame is created at the same time to store information such as local variable tables, operation stacks, dynamic links, method exits, and so on. The call to completion of each method means that a frame is loaded into the stack in the VM stack. If the thread requests a stack depth greater than the virtual machine allows, the Stackoverflowerror exception is thrown, and if the VM stack can be dynamically extended (a fixed-length VM stack is allowed in the VM spec), The OutOfMemoryError exception is thrown when the extension cannot request enough memory.
3. Local method stack-native method service Sun Spothot The above two stacks into one.
4. Heap
The stack for each thread is private to the thread, and the heap is shared by all threads. When we new an object, the object is assigned to the heap. But the heap, is not a simple concept, the heap is divided into a lot of areas, why the heap is divided into so many areas, this is for the JVM's memory garbage collection, it seems that the farther away from the garbage collection, the current JVM GC is collected by generation, the heap area is broadly divided into three chunks: the new generation, the old generation, Lasting generation (virtual), the new generation is also divided into Eden, S0 (from survivor), S1 district (to survivor). When you create a new object, the basic small object, the short life of the object will be placed in the new generation of Eden, when Eden is full, there is a small range of GC (minor GC), the entire Cenozoic full, there will be a large range of GC (major GC), the new generation of some of the objects transferred to the old generation.
The development of JIT compilers, and the maturation of escape analysis techniques, not all instances of objects are here.
5. Method area
In fact, the permanent generation (Permanent Generation), the method area contains the structure information of each class, including constant pool, field description, method description, and so on. The restrictions on this area in the VM space description are very loose, with the exception of the Java heap, which does not require contiguous memory, can optionally be fixed size or extensible, and can even choose not to implement garbage collection. Relatively speaking, the garbage collection behavior in this area is relatively small occurrence, but not some of the description of the permanent generation will not occur GC (at least for the current mainstream commercial JVM implementation is so), here the GC is mainly for the constant pool of recycling and unloading classes, although the recovery of "score" is generally less than satisfactory, Especially class unloading, the conditions are quite harsh.
6. Constant Pool
class file In addition to the class version, fields, methods, interfaces and other information such as descriptions, there is also a constant table (Constant_pool table), for the compilation of the known constants, which will be loaded in the class load into the method area (permanent generation) storage. However, the Java language does not require constants to enter the method area constant pool only if the content of the const table of the class is pre-compiled, and the new content can be put into Chang (the most typical String.intern () method) during the run time.
On the garbage collection, not much to say in this, flow to the garbage collection that chapter in detail. There are also non-blocking algorithms (CAS) that are based on CPU primitives compared and exchanged for Java synchronization, but this has been implemented in Java concurrency packages.
7. Direct Memory
Not belonging to JMM, in the introduction of NIO, channel and buffer-based I/O patterns can be used to directly allocate out-of-heap memory using the native function, and then operate on a directbytebuffer that is present in the heap as this fast memory reference, which improves performance. Avoids copying data back and forth between the Java heap and the native heap.

java-Concurrency-Thread safety

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.