Five Methods of Java multithreading synchronization _java

Source: Internet
Author: User

Why to Thread Sync

Because when we have more than one thread to access a variable or object at the same time, if the threads have both read and write operations, the value of the variable or the state of the object is confused, resulting in an exception to the program. For example, if a bank account is operated by two threads at the same time, one takes 100, and one saves 100 dollars. Assuming that there were 0 dollars in the account, what would happen if the money-picking thread and the savings thread occurred at the same time? The money is not successful, the account balance is 100. The money was successful, the account balance is 0. which is it? It's hard to say clearly. Therefore multithreading synchronization is to solve this problem.

Code at different steps

Bank.java package threadtest; /** * @author WW * * */public class Bank {private int count =0;//account balance//Save public void Addmoney (int) 
    ) {count +=money; 
  System.out.println (System.currenttimemillis () + "deposit in:" +money); 
      ///Withdraw public void Submoney (INT-Money) {if (Count-money < 0) {System.out.println ("insufficient balance"); 
    Return 
    Count-=money; 
  System.out.println (+system.currenttimemillis () + "Remove:" +money); 
  //Query public void Lookmoney () {System.out.println ("account balance:" +count); 
 
}} Syncthreadtest.java package threadtest; 
 
    public class Syncthreadtest {public static void main (String args[]) {Final Bank bank=new Bank (); Thread Tadd=new Thread (new Runnable () {@Override public void run () {//TODO auto-generated Meth 
          OD stub while (true) {try {thread.sleep (1000); catch (Interruptedexception e) {//TODO auto-gEnerated Catch block E.printstacktrace (); 
          } bank.addmoney (100); 
          Bank.lookmoney (); 
 
        System.out.println ("\ n"); 
 
    } 
      } 
    }); Thread tsub = new Thread (new Runnable () {@Override public void run () {//TODO auto-generated Me 
          Thod stub while (true) {Bank.submoney (100); 
          Bank.lookmoney (); 
          System.out.println ("\ n"); 
          try {thread.sleep (1000); 
          catch (Interruptedexception e) {//TODO auto-generated catch block E.printstacktrace (); 
    }   
        } 
      } 
    }); 
 
    Tsub.start (); 
  Tadd.start ();  } 
 
}

The code is very simple, I will not explain, see how the results of the operation? Intercepted a part of it is not very messy, there is no understanding of writing.

Insufficient balance
Account Balance: 0

Insufficient balance
Account balance: 100

1441790503354 Deposit in: 100
Account balance: 100

1441790504354 Deposit in: 100
Account balance: 100

1441790504354 out: 100
Account balance: 100

1441790505355 Deposit in: 100
Account balance: 100

1441790505355 out: 100
Account balance: 100

Second, the use of synchronization code

(1) Synchronization method:

That is, the Synchronized keyword modification method. Because each object in Java has a built-in lock, the built-in lock protects the entire method when the method is decorated with this keyword. You need to obtain a built-in lock before calling this method, otherwise you are in a blocking state.

The modified Bank.java

And look at the results of the operation:

Insufficient balance
Account Balance: 0

Insufficient balance
Account Balance: 0

1441790837380 Deposit in: 100
Account balance: 100

1441790838380 out: 100
Account Balance: 0
1441790838380 Deposit in: 100
Account balance: 100

1441790839381 out: 100
Account Balance: 0

Instant feeling can understand it.

Note: The Synchronized keyword can also modify the static method, and if the static method is invoked, the entire class will be locked

(2) Sync code block

That is, a block of statements decorated with the Synchronized keyword. A block of statements decorated by this keyword is automatically added with a built-in lock, which enables synchronization

The Bank.java code is as follows:

Package threadtest; 
 
/** 
* @author WW * * */Public 
class Bank { 
 
  private int count =0;//account balance 
 
  //save  Public void Addmoney (int money) { 
 
    synchronized (this) { 
      count +=money; 
    } 
    System.out.println (System.currenttimemillis () + "deposit in:" +money); 
  } 
 
  Take money 
  public  void Submoney (int money) { 
 
    synchronized (this) { 
      if (Count-money < 0) 
        { SYSTEM.OUT.PRINTLN ("Insufficient balance"); 
        return; 
      } 
      Count-=money; 
    } 
    System.out.println (+system.currenttimemillis () + "Remove:" +money); 
  } 
 
  Query public 
  void Lookmoney () { 
    System.out.println (account balance: +count); 
  } 
 

The results of the operation are as follows:

Insufficient balance
Account Balance: 0

1441791806699 Deposit in: 100
Account balance: 100

1441791806700 out: 100
Account Balance: 0

1441791807699 Deposit in: 100
Account balance: 100

Effect and method a similar.

Note: Synchronization is a high cost operation, so you should minimize the content of the synchronization. There is usually no need to synchronize the entire method, using the synchronized code block to synchronize the critical code.

(3) Implement thread synchronization using special domain variables (Volatile)

The A.volatile keyword provides a lock-free mechanism for accessing domain variables
B. Using the volatile modifier field is equivalent to telling the virtual machine that the domain may be updated by another thread
C. Therefore, each time the domain is used, it is recalculated instead of using the value in the Register
D.volatile does not provide any atomic operations, nor can it be used to modify the final type of variable

The Bank.java code is as follows:

Package threadtest; 
 
/** 
* @author WW * * */Public 
class Bank { 
 
  private volatile int count = 0;//account balance 
 
  //Save 
  Public void Addmoney (int money) { 
 
    count + = money; 
    System.out.println (System.currenttimemillis () + "deposit:" + money); 
  } 
 
  Take money to public 
  void Submoney (int money) { 
 
    if (Count-money < 0) { 
      System.out.println ("Insufficient balance"); 
      return; 
    } 
    Count-= money; 
    System.out.println (+system.currenttimemillis () + "out:" + money); 
  } 
 
  Query public 
  void Lookmoney () { 
    System.out.println ("Account balance:" + count); 
  } 
} 

What is the effect of the operation?

Insufficient balance
Account Balance: 0

Insufficient balance
Account balance: 100

1441792010959 Deposit in: 100
Account balance: 100

1441792011960 out: 100
Account Balance: 0

1441792011961 Deposit in: 100
Account balance: 100

is not understand again, again disorderly. What is this for? Because volatile cannot guarantee atomic operation, volatile cannot replace synchronized. In addition, volatile organizes the compiler to optimize the code, so it does not apply if it is not used. The idea is that every time a thread wants to access a variable that is volatile decorated, it reads from memory rather than in the cache, so each thread accesses the same variable value. This ensures synchronization.

(4) using a reentrant lock to implement thread synchronization

A java.util.concurrent package was added to the JavaSE5.0 to support synchronization. The Reentrantlock class is a lock that is reentrant, mutually exclusive, and implements the lock interface, which has the same basic behavior and semantics as the use of the Synchronized method, and extends its capabilities.
Common methods for Reenreantlock classes are:
Reentrantlock (): Create a Reentrantlock instance
Lock (): Get lock
Unlock (): Release lock
Note: Reentrantlock () also has a construction method to create a fair lock, but because it can greatly reduce the efficiency of the program, it is not recommended to use
The Bank.java code is modified as follows:

Package threadtest; 
 
Import Java.util.concurrent.locks.Lock; 
Import Java.util.concurrent.locks.ReentrantLock; 
 
/** 
* @author WW 
* * * 
/Public 
class Bank { 
 
  private int count = 0;//account balance 
 
  //need to declare this lock 
  private Lo CK lock = new Reentrantlock (); 
 
  Save for public 
  void Addmoney (int money) { 
    lock.lock ();//Lock 
    try{ 
    count = money; 
    System.out.println (System.currenttimemillis () + "deposit:" + money); 
 
    } finally{ 
      Lock.unlock ();//Unlock 
    } 
 
  ///Withdraw public 
  void Submoney (int money) { 
    lock.lock (); 
    try{ 
 
    if (Count-money < 0) { 
      System.out.println ("Insufficient balance"); 
      return; 
    } 
    Count-= money; 
    System.out.println (+system.currenttimemillis () + "out:" + money); 
    } finally{ 
      Lock.unlock (); 
    } 
 
  Query public 
  void Lookmoney () { 
    System.out.println ("Account balance:" + count); 
  } 
} 

What about the running effect?

Insufficient balance
Account Balance: 0

Insufficient balance
Account Balance: 0

1441792891934 Deposit in: 100
Account balance: 100

1441792892935 Deposit in: 100
Account balance: 200

1441792892954 out: 100
Account balance: 100

The effect is similar to the first two methods.

If the Synchronized keyword meets the needs of the user, use synchronized because it simplifies the code. If you need more advanced features, use the Reentrantlock class, pay attention to release the lock in time, otherwise there will be deadlock, usually in finally code release lock

(5) Using local variables to achieve thread synchronization

The Bank.java code is as follows:

Package threadtest; 
 
/** 
* @author WW * * */Public 
class Bank { 
 
  private static threadlocal<integer> count = new Threa Dlocal<integer> () { 
 
    @Override 
    protected Integer initialvalue () { 
      //TODO auto-generated method stub< C10/>return 0; 
    } 
 
  ; 
 
  Save for public 
  void Addmoney (int money) { 
    count.set (Count.get () +money); 
    System.out.println (System.currenttimemillis () + "deposit:" + money); 
 
  } 
 
  Take money to public 
  void Submoney (int money) { 
    if (Count.get () – Money < 0) { 
      System.out.println ("Insufficient balance"); 
   
    return; 
    } 
    Count.set (Count.get ()-money); 
    System.out.println (+system.currenttimemillis () + "out:" + money); 
  } 
 
  Query public 
  void Lookmoney () { 
    System.out.println ("Account balance:" + count.get ()); 
  } 
 

   

Operation Effect:

Insufficient balance
Account Balance: 0

Insufficient balance
Account Balance: 0

1441794247939 Deposit in: 100
Account balance: 100

Insufficient balance
1441794248940 Deposit in: 100
Account Balance: 0

Account balance: 200

Insufficient balance
Account Balance: 0

1441794249941 Deposit in: 100
Account balance: 300

See the effect of the operation, a beginning confused, how only to save, not to take AH? Look at the threadlocal principle:

If you use threadlocal to manage variables, each thread that uses the variable obtains a copy of the variable, and the replicas are independent of each other so that each thread can modify its own copy of the variable without affecting the other threads. Now understand that each thread is running a copy, that is to save and withdraw money is two accounts, the same knowledge name. So the effect will happen.

Threadlocal and synchronization mechanism

A.threadlocal and synchronization mechanism are all to solve the access conflict problem of the same variable in multiple threads
B. The former uses a "space for time" approach, the latter using the "time for space" approach

It's all clear now. Each has its pros and cons, each has a suitable scenario, I hope this article can be more in-depth understanding of Java Multithreading Synchronization Help.

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.