Java Multithreading Examples (iii) _java

Source: Internet
Author: User

This article is mainly followed by two threads in the previous article to summarize the problem of thread safety in Java multiple threads.

A typical Java thread-safe example

public class ThreadTest {public static void main (string[] args) {The account account = new Account ("123456", 1000);
  Drawmoneyrunnable drawmoneyrunnable = new Drawmoneyrunnable (account, 700);
  Thread myThread1 = new Thread (drawmoneyrunnable);
  Thread myThread2 = new Thread (drawmoneyrunnable);
  Mythread1.start ();
 Mythread2.start ();
 } class Drawmoneyrunnable implements Runnable {private account account;

 Private double drawamount;
  Public drawmoneyrunnable (account account, double drawamount) {super ();
  This.account = account;
 This.drawamount = Drawamount; public void Run () {if (Account.getbalance () >= drawamount) {//1 System.out.println ("success of the money, take out the amount is:" + Drawamou
   NT);
   Double balance = account.getbalance ()-drawamount;
   Account.setbalance (balance);
  System.out.println ("Balance is:" + balance);
 The class Account {private String accountno;

 private double balance; Public account () {} public account (String Accountno, double balance) {THis.accountno = Accountno;
 This.balance = balance;
 Public String Getaccountno () {return accountno;
 } public void Setaccountno (String accountno) {this.accountno = Accountno;
 Public double GetBalance () {return balance;
 The public void setbalance (double balance) {this.balance = balance; }

}

The above example is easy to understand, there is a bank card, which has 1000 of the balance, the program simulates you and your wife at the same time in the cash machine to take money to operate the scene. Run this program more than once, possibly with multiple different combinations of output results. One of the possible outputs is:

1 Get the money successfully, take out the amount is: 700.0
2 The balance is: 300.0
3 Get the money successfully, take out the amount is: 700.0
4 The balance is:-400.0

That is to say, for a bank card with only 1000, you can take out 1400 altogether, which is obviously problematic.

After analysis, the problem is the uncertainty of execution in a Java multithreaded environment. The CPU may be randomly switching between multiple threads in a ready state, so it is likely that when Thread1 executes to//1 code, the judgment condition is true, the CPU switches to Thread2, executes//1 code, and finds that it is still true, Then execute the thread2, then switch to Thread1, then finish. At this point, the results will appear.

Therefore, when it comes to threading security, it means that access to shared resources in a multithreaded environment can cause inconsistencies in this shared resource. Therefore, to avoid thread-safety issues, concurrent access to this shared resource in a multithreaded environment should be avoided.

Two. Sync method

The method definition of access to shared resources adds the Synchronized keyword modification, making this method known as the synchronization method. This method can be easily understood as a lock object that is the object itself of the current method. In a multithreaded environment, when this method is executed, the synchronization lock is first acquired (and at most one thread is available), and the lock object is released only after the thread finishes the synchronization method, and other threads are able to acquire the synchronization lock, and so on ...

In the example above, the shared resource is the account object, and thread-safety issues can be resolved when the synchronization method is used. Just add the Synshronized keyword before the run () method.

 Public synchronized void Run () {
  
 //...
 
}

Three. Sync code block

As discussed above, solving thread-safety problems simply limits the uncertainty of access to shared resources. When using the synchronization method, the whole method body becomes synchronous execution state, which may cause the synchronization scope to be too large, so that the code that needs to be synchronized can be synchronized in another way--synchronizing the code block to solve.

The format of the synchronized code block is:

 Synchronized (obj) {
    
  //...
 
 }

Where obj is the lock object, it is important to choose which object to use as a lock. Typically, you select this shared resource object as the lock object.

As in the previous example, it is best to select the account object as the lock object. (This is also possible, of course, because the creation thread uses the Runnable method, and if the thread is created directly by inheriting thread, using this object as a sync lock does not actually work because it is a different object.) Therefore, you need to be cautious when choosing a sync lock ... )

Four. Lock Object Sync Lock

As we can see above, because the selection of the synchronization lock object needs to be so careful, is there any simple point of solution? It is convenient to decouple the synchronized lock object and the shared resource, and to solve the thread safety problem.

Using the lock object to synchronize locks is a convenient way to solve this problem, and the only thing to note is that the lock object needs to have a one-to-one relationship with the resource object as well. The general format for lock object Sync locks is:

Class X {
 
 //display defines the lock synchronization lock object, which has a one-to-one relationship to the shared resource
 private final lock lock = new Reentrantlock ();
 
 public void M () {
  //Lock
  Lock.lock ();
  
  //... Code
  
  /Release Lock lock Lock.unlock () required for thread-safe synchronization
  ;
 }
 

Five. Wait ()/notify ()/notifyall () thread communication

These three methods are mentioned in the blog post Java Summary series: Java.lang.Object, although these three methods are mostly used in multithreading, but are actually local methods in the Object class. Therefore, theoretically, any object objects can be the keynote of the three methods, in the actual multithreaded programming, only the synchronization lock object to tune the three methods to complete the thread communication between multithreading.

Wait (): Causes the current thread to await and bring it into a wait-blocking state. Wake this thread until the other thread calls the Notify () or Notifyall () method of the synchronization lock object.

Notify (): Wakes a single thread waiting on this synchronization lock object, and if more than one thread waits on this synchronization lock object, any one of the threads will be selected for the wakeup operation, and the awakened thread may be executed only if the front thread discards the lock on the synchronization lock object.

Notifyall (): Wakes all threads waiting on this synchronization lock object, and can execute awakened threads only if the thread discards the lock on the synchronization lock object.

Package Com.qqyumidi;

  public class ThreadTest {public static void main (string[] args) {The account account = new Account ("123456", 0);
  Thread drawmoneythread = new Drawmoneythread ("Fetch thread", account, 700);

  Thread depositemoneythread = new Depositemoneythread ("Saving thread", account, 700);
  Drawmoneythread.start ();
 Depositemoneythread.start ();
 } class Drawmoneythread extends Thread {private account account;

 private double amount;
  Public Drawmoneythread (String threadname, account account, double amount) {super (threadname);
  This.account = account;
 This.amount = amount;
  public void Run () {for (int i = 0; i < i++) {Account.draw (amount, I);
 Class Depositemoneythread extends Thread {private account account;

 private double amount;
  Public Depositemoneythread (String threadname, account account, double amount) {super (threadname);
  This.account = account;
 This.amount = amount; public void Run () {for (int i = 0; i < i++){Account.deposite (amount, I);
 The class Account {private String accountno;
 private double balance;

 Identify whether there is a deposit in the account private Boolean flag = false;
  Public account () {} public account (String Accountno, double balance) {this.accountno = Accountno;
 This.balance = balance;
 Public String Getaccountno () {return accountno;
 } public void Setaccountno (String accountno) {this.accountno = Accountno;
 Public double GetBalance () {return balance;
 The public void setbalance (double balance) {this.balance = balance; /** * Save money * * @param depositeamount/public synchronized void Deposite (double depositeamount, int i) {i  F (flag) {//The account has been saved, the current thread will need to wait to block the try {System.out.println (Thread.CurrentThread (). GetName () + "Start waiting operation"
    + "--i=" + i);
    Wait ();
   1 System.out.println (Thread.CurrentThread (). GetName () + "executed the wait operation" + "--i=" + i);
   catch (Interruptedexception e) {e.printstacktrace (); } ElSE {//start saving System.out.println (Thread.CurrentThread () getName () + "deposit:" + Depositeamount + "--i=" + i);
   Setbalance (balance + depositeamount);

   Flag = true;

   Wake Up Other threads notifyall ();
   2 try {thread.sleep (3000);
   catch (Interruptedexception e) {e.printstacktrace ();
  } System.out.println (Thread.CurrentThread (). GetName () + "--Save money--Execute" + "--i=" + i); }/** * Withdraw money * * @param drawamount/public synchronized void Draw (double drawamount, int i) {if (!flag) {//There is no one in the account to save money, at this point the current thread needs to wait for blocking try {System.out.println (Thread.CurrentThread (). GetName () + "start to perform the wait operation" + "executes the W
    AIT operation "+"--i= "+ i);
    Wait ();
   System.out.println (Thread.CurrentThread (). GetName () + "performed a wait operation" + "executes the wait operation" + "--i=" + i);
   catch (Interruptedexception e) {e.printstacktrace ();
   } else {//start to withdraw money System.out.println (Thread.CurrentThread (). GetName () + "withdraw money:" + Drawamount + "--i=" + i); Setbalance (GetBalance ()-DRawamount);

   Flag = false;

   Wake Up Other threads notifyall (); System.out.println (Thread.CurrentThread (). GetName () + "--take money--execute" + "--i=" + i); 3}}}

The

Example above demonstrates the use of Wait ()/notify ()/notifyall (). Some of the output results are:

The money-fetching thread starts to perform a wait operation--i=0
Saving thread Deposit: 700.0--i=0
Saving thread--saving money--execution completed--i=0
The money-saving thread starts to perform a wait operation-I=1
The money-fetching thread performs a wait operation and performs a wait operation-i=0
Withdraw money thread to withdraw money: 700.0--I=1
Draw Money thread--take money--execution complete--i=1
The money-fetching thread starts to perform a wait operation--i=2
The save thread performs a wait operation--I=1
Saving thread Deposit: 700.0--i=2
Saving thread--saving money--execution completed--i=2
The money-fetching thread performs a wait operation and performs a wait operation-i=2
Withdraw money thread to withdraw money: 700.0--i=3
Draw Money thread--take money--execution complete--i=3
The money-fetching thread starts to perform a wait operation--i=4
Saving thread Deposit: 700.0--i=3
Saving thread--saving money--execution completed--i=3
The money-saving thread starts to perform a wait operation-i=4
The money-fetching thread performs a wait operation and performs a wait operation-i=4
Withdraw money thread to withdraw money: 700.0--i=5
Draw Money thread--take money--execution complete--i=5
The money-fetching thread starts to perform a wait operation--i=6
The save thread performs a wait operation--i=4
Saving thread Deposit: 700.0--i=5
Saving thread--saving money--execution completed--i=5
The money-saving thread starts to perform a wait operation-i=6
The money-fetching thread performs a wait operation and performs a wait operation-i=6
Withdraw money thread to withdraw money: 700.0--i=7
Draw Money thread--take money--execution complete--i=7
The money-fetching thread starts to perform a wait operation--i=8
The save thread performs a wait operation--i=6
Saving thread Deposit: 700.0--i=7

Therefore, we need to pay attention to the following points:

After the 1.wait () method executes, the current thread immediately enters the pending blocking state, and the following code does not execute;

When the 2.notify ()/notifyall () method executes, it wakes up (any-notify ()/All-notifyall ()) thread object on this synchronization lock object, but the synchronization lock object is not released at this time, that is, if notify ()/ Notifyall () is followed by code, and will continue, knowing that the current thread is finished before releasing the synchronized lock object;

3.notify ()/notifyall () after execution, if the right has a sleep () method, will cause the current thread into the blocking state, but the synchronization object lock is not released, still keep their own, then will continue to execute this thread, next to the same 2;

4.wait ()/notify ()/nitifyall () the communication or collaboration between threads is based on different object locks, so if the different synchronization object locks will lose their meaning, at the same time, the synchronization object lock is best to maintain one by one correspondence with the shared resource object;

5. When the wait thread wakes up and executes, it continues after the last Wait () method code executed.

Of course, the above example is relatively simple, just for the simple example of the use of Wait ()/notify ()/noitifyall () method, but in essence, it is already a simple producer-consumer model.

Series of articles:

Java Multithreading Example Explanation (i)
Java Multithreading Examples (ii)
Java Multithreading Examples (iii)

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.