Java Multithreading (three) conditional objects

Source: Internet
Author: User

Reprint Please specify Source:http://blog.csdn.net/xingjiarong/article/details/47417383
In the previous blog, we learned to use Reentrantlock to control threads to access the same data, preventing race Condition from appearing. This time, we continue in-depth study, learning about the conditional objects in Java, conditional objects in multi-threaded synchronization used more.

First, let's introduce the critical section.

Critical section: In a synchronous program design, a critical section refers to a program fragment that accesses a shared resource that has an attribute that cannot be accessed concurrently by multiple threads. When a thread enters a critical section, other threads or processes must wait, and in some cases, special methods must be taken at the entry and exit points of the critical section to ensure that these pooled resources are mutually exclusive.

Now let's look at a new example, which is a bank transfer example. In the bank class, we declare a 10-size array to represent 10 accounts in the bank, and the corresponding value is the corresponding amount in the account. The bank provides a way to transfer the funds from the account, transferring amount funds to the to account. The method of obtaining the total amount of these accounts is also provided, GETTOTALBALABCE (), since the transfer of funds takes place in these 10 accounts, so no matter how the transfer, the total amount should be unchanged.

Bank.java

ImportJava.util.concurrent.locks.ReentrantLock; Public  class Bank {    /** * Using arrays to simulate bank accounts * *    Private Final DoubleAccounts[];PrivateReentrantlock lock =NewReentrantlock (); Public Bank() {accounts =New Double[Ten];/ * Initialize so that each account is initially initialbalance money */         for(inti =0; I <Ten; i++) Accounts[i] = +; }/** * Method of transfer of funds * * @param from * source account * @param to * target accounts * @param Amount * Transfer Amount * *     Public void Transfer(intFromintTo,DoubleAmount) {Lock.lock ();Try{if(Accounts[from] < amount)returnSystem.out.print (Thread.CurrentThread ());            Accounts[from]-= amount; System.out.printf ("%5.2f from%d to%d", amount, from, to);            Accounts[to] + = amount; System.out.printf ("Total balance:%5.2f\n", Gettotalbalance ()); }Catch(Exception e)        {E.printstacktrace (); }finally{Lock.unlock (); }    }/** * Get the total amount of all accounts * * @return  */     Public Double gettotalbalance() {lock.lock ();Doublesum =0;Try{ for(Doublea:accounts) sum + = A; }finally{Lock.unlock (); }returnSum }/** * Get the number of accounts now * * @return  * *     Public int size() {returnAccounts.length; }}

Transferrunnable This class implements the Runnable interface, we take him as a thread in the main function, and its run method is to generate a random target account and transfer the amount, and then call the Bank class method to transfer funds to the target account.

Transferrunnable.java

 Public  class transferrunnable implements Runnable{    PrivateBank Bank;Private intFromaccount; Public transferrunnable(Bank B,intfrom) {bank=b;    Fromaccount=from; } Public void Run(){Try{ while(true)            {intToaccount = (int) (Bank.size () *math.random ());DoubleAmount = +*math.random ();                Bank.transfer (Fromaccount, Toaccount, amount); Thread.Sleep ( +); }        }Catch(Exception e)        {E.printstacktrace (); }    }   }

In the main program, we created 10 threads, each of which transfers a certain amount of money from a corresponding account to a random account.
Main.java

 Public classMain { Public Static void Main(string[] args) {Bank b =NewBank (); thread[] Threadarray =Newthread[Ten]; for(inti =0; I <Ten; i++) {Threadarray[i] =NewThread (NewTransferrunnable (b, i)); } for(intI=0;i<Ten; i++) {Threadarray[i].start (); }    }}

In this program there are common variables-10 bank account funds, so there is a corresponding critical section of the--bank class of transfer method and Gettotalbalabce method, if the critical section is not protected, it will cause multiple threads to enter the critical section simultaneously, resulting in a false result, Readers can experiment, will reentrantlock lock the place are removed, see whether the total amount will change, in my experiment, not only the total amount of wrong, even the printed statement order is not correct, indicating a thread in System.out.printf () has been interrupted by other threads in the process.

Looking at this example, I believe you are more proficient in the use of Reentrantlock.

Now let's consider this question, as you can see in the transfer method, if the amount of money in the account is not enough to return immediately without the transfer of funds, I do not want to deal with this now. I want to do this, and if the account is underfunded, wait until the other accounts transfer enough money to the account before the transfer of funds occurs.

The problem is that the thread that is manipulating the account has been given lock, the other threads are no longer able to enter the lock method, and it is impossible to transfer the corresponding funds to the account, so that the thread must give up lock control and let the other threads get it.

Java provides the conditional object, condition class, to match the Reentrantlock to achieve the control of the critical section, we make the following changes to the Bank class.

ImportJava.util.concurrent.locks.Condition;ImportJava.util.concurrent.locks.ReentrantLock; Public  class Bank {    /** * Using arrays to simulate bank accounts * *    Private Final DoubleAccounts[];PrivateReentrantlock lock =NewReentrantlock ();PrivateCondition Condition; Public Bank() {accounts =New Double[Ten];/ * Initialize so that each account is initially initialbalance money */         for(inti =0; I <Ten; i++) Accounts[i] = +;    Condition = Lock.newcondition (); }/** * Method of transfer of funds * * @param from * source account * @param to * target accounts * @param Amount * Transfer Amount * *     Public void Transfer(intFromintTo,DoubleAmount) {Lock.lock ();Try{ while(Accounts[from] < amount) condition.await ();            System.out.print (Thread.CurrentThread ());            Accounts[from]-= amount; System.out.printf ("%5.2f from%d to%d", amount, from, to);            Accounts[to] + = amount; System.out.printf ("Total balance:%5.2f\n", Gettotalbalance ());        Condition.signalall (); }Catch(Exception e)        {E.printstacktrace (); }finally{Lock.unlock (); }    }/** * Get the total amount of all accounts * * @return  */     Public Double gettotalbalance() {lock.lock ();Doublesum =0;Try{ for(Doublea:accounts) sum + = A; }finally{Lock.unlock (); }returnSum }/** * Get the number of accounts now * * @return  * *     Public int size() {returnAccounts.length; }}

First, a condition class object reference variable condition is declared, initialization in the bank's construction method, initialization is the method of calling the Reentrantlock class Newcondition (), When you describe a condition object that relies on a Reentrantlock object, a Reentrantlock object can create multiple conditional objects, and names are usually named with controlled conditions.

Then in the transfer method, the following two lines are key:

while (accounts[from] < amount)    condition.await();

Using the while loop to detect the balance of the account, if the balance is insufficient to call the await () method, await () will block the thread and release the lock held by the thread, then the other threads can enter the critical section, when the balance of the account to meet the conditions, waiting for the thread will not be active wake up, Until one of the threads calls the Signalall () method. The Signalall () method wakes up all the threads that are waiting because they do not meet the criteria, but the thread does not necessarily continue to execute down because the thread is not told when the Signalall () wakes up, it is not telling the thread that your condition is satisfied, you can continue to execute down, but to tell the thread that the condition is changing, You can re-detect if the condition is satisfied. If the condition is met, then only one thread can continue to execute, because once an object has a lock on the critical section, the other threads cannot enter the critical section anymore. So when should the Signalall () method be called, from experience should be called when the state of the object facilitates the direction of the waiting thread to change. Here we re-call after the transfer of funds, because after the transfer of funds, other threads are likely to meet the conditions.

Note: Typically, the call to await () should be in the following form of the loop body:

whileto proceed))    condition.await();

The while loop here cannot be replaced with an IF condition statement because the thread that is woken up by another thread with the Signalall method is simply that the condition may be satisfied, not the condition must be satisfied, and if it does not continue to be detected without the while loop, it will cause a thread that is not satisfied to continue to execute, thus generating errors.

When a thread has a lock on a condition, it can only invoke await (), signalall (), signal () three methods on that condition, now let's talk about the third method.

The difference between signal and signalall is that signal does not wake up all of the waiting threads, but instead randomly chooses a thread to wake up, while Signalall wakes up all the waiting threads.

Finally attached Source: http://download.csdn.net/detail/xingjiarong/9010675

In the next blog, I will introduce Java synchronized keyword, I hope to learn together with you progress, please continue to pay attention to my blog, if you support my words, the top of me.

Copyright NOTICE: This article for Bo Master original article, reproduced please indicate the source, view the original article, please visit: Http://blog.csdn.net/xingjiarong

Java Multithreading (three) conditional objects

Related Article

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.