Tag: Instead of lock line operation catch success div his ATI Sys
Synchronizing code blocks
synchronized (obj) { // code block }
OBJ is the synchronization monitor, and the above code means that the thread must obtain a lock on the synchronization monitor before it starts executing the code in the synchronization code block.
The code in the code block is the execution code, which is a part of the code in a method, and synchronized (obj) {} can only appear in a method. Such as:
Public void Test () { synchronized (obj) { // code block } }
Instead of appearing in another location, the following is an error:
Public class Test { void Test (string[] strs) { }
//error, can only appear in a method synchronized (obj) { }}
Example of a synchronous code block:
Define an account class for storing the accounts amount
classAccount {//account Balance Private Doublebalance; PublicAccount (Doublebalance) { This. Balance =balance; } //Set Balance Public voidSetbalance (Doublebalance) { This. Balance =balance; } //Withdraw Balance Public DoubleGetBalance () {returnbalance; }}
Define 1 thread classes to operate on an account (take out the balance in the account), the thread class does not contain a synchronization code block
classDrawmoneyextendsThread {PrivateAccount Account;//account to be taken Private DoubleAmount//Withdraw Amount PublicDrawmoney (Account account,Doubleamount) { This. Account =Account ; This. Amount =amount; } //Take out the balance in account and take out a quantity of amount Public voidrun () {//if the balance in account is greater than or equal to amount, the money is successful if(Amount <=account.getbalance ()) {System.out.println (GetName ()+ ":" + "Get Money:" +amount); //thread hibernation 2 ms Try{Thread.Sleep (2); } Catch(interruptedexception e) {//TODO auto-generated Catch blockE.printstacktrace (); } account.setbalance (Account.getbalance ()-amount); System.out.println (GetName ()+ ":" + "Balance is" +account.getbalance ()); } ElseSystem.out.println ("The balance is not enough"); }}
Use the account class and the Drawmoney class above to define an accounts, two users, two users to operate the account simultaneously (withdraw money).
Public class synchronizedtest { publicstaticvoid main (string[] args) { New Account (+); New Drawmoney (account,N); New Drawmoney (account,N); User1.start (); User2.start (); }}
Operation Result:
Thread-0: Get money:70.0
Thread-1: Get money:70.0
Thread-0: Balance is 30.0
Thread-1: Balance is-40.0
From the above, the second user to withdraw money error, the balance should not be less than 0. This is due to the fact that two concurrently running threads (at the same time the user who is taking the money) operate on the account at the same time, rather than one fetch, and then to the next. User 1 before the time to modify the balance, User 2 began to withdraw money.
Modify the above thread class to synchronize the take money operation
classDrawcashextendsThread {PrivateAccount Account ; Private Doubleamount; PublicDrawcash (Account account,Doubleamount) { This. Account =Account ; This. Amount =amount; } Public voidrun () {//using account as the synchronization monitor, the thread needs to lock the account before executing the following code synchronized(account) {if(Amount <=account.getbalance ()) {System.out.println (GetName ()+ ":" + "Get Money:" +amount); Try{Thread.Sleep (2); } Catch(interruptedexception e) {//TODO auto-generated Catch blockE.printstacktrace (); } account.setbalance (Account.getbalance ()-amount); System.out.println (GetName ()+ ":" + "Balance is" +account.getbalance ()); } ElseSystem.out.println (GetName ()+ ":" + "the balance is not enough"); } }}
Then
Public class synchronizedtest { publicstaticvoid main (string[] args) { New Account (+); New Drawcash (account,N); New Drawcash (account,N); User1.start (); User2.start (); }}
Operation Result:
Thread-0: Get money:70.0
Thread-0: Balance is 30.0
Thread-1: The balance is not enough
Lock the Monitor account when the first thread executes the synchronization code block, and the second thread will need to lock the monitor account when executing the synchronization code block.
At this point, the account is locked by thread 0, so thread 1 only has the synchronization code block that threads 0 executes before it can execute its synchronization code block.
Use Drawmoney and Drawcash to define a user and withdraw money from the same account.
Public class synchronizedtest { publicstaticvoid main (string[] args) { New Account (+); New Drawcash (account,N); New Drawmoney (account,N); User1.start (); User2.start (); }}
Operation Result:
Thread-0: Get money:70.0
Thread-1: Get money:70.0
Thread-0: Balance is 30.0
Thread-1: Balance is-40.0
The result is still wrong, because thread 0 needs to lock the monitor account, but thread 1 does not need to, so it is still a thread insecure to access it in this case.
Synchronization method
The method that is modified by synchronized is the synchronous method, and the synchronization monitor of the synchronous method is this, that is, the object corresponding to the method (the object generated by the class in which the method resides).
Public synchronized void Draw () { }
To invoke the draw () method, a thread needs to lock the corresponding object of Draw ().
Modify the account class to add a synchronization method
classAccount {//account Balance Private Doublebalance; PublicAccount (Doublebalance) { This. Balance =balance; } Public synchronized voidDrawDoubleamount) { if(Amount >balance) System.out.println (Thread.CurrentThread (). GetName ()+ ":" + "Balance is not Enough"); Else{System.out.println (Thread.CurrentThread (). GetName ()+ " : " +amount); Balance-=amount; System.out.println (Thread.CurrentThread (). GetName ()+ ":" + "Balance is" +balance); } }}
Modifying the Drawmoney class
classDrawmoneyextendsThread {PrivateAccount Account;//account to be taken Private DoubleAmount//Withdraw Amount PublicDrawmoney (Account account,Doubleamount) { This. Account =Account ; This. Amount =amount; } //Take out the balance in account and take out a quantity of amount Public voidrun () {Account.draw (amount); }}
Then
Public class synchronizedtest { publicstaticvoid main (string[] args) { New Account (+); New Drawmoney (account,N); New Drawmoney (account,N); User1.start (); User2.start (); }}
Operation Result:
Thread-0:70.0
Thread-0: Balance is 30.0
Thread-1: Balance is not enough
Visible, threads are safe
Thread 0 calls the draw () method when the lock monitor account,1 thread calls draw () also needs to lock the monitor account,
At this point, the account is locked by thread 0, so thread 1 will only be called after the call is completed in line 0.
The synchronization methods described above can also be implemented with synchronous code blocks:
classAccount {//account Balance Private Doublebalance; PublicAccount (Doublebalance) { This. Balance =balance; } Public voidDrawDoubleamount) { synchronized( This) { if(Amount >balance) System.out.println (Thread.CurrentThread (). GetName ()+ ":" + "Balance is not Enough"); Else{System.out.println (Thread.CurrentThread (). GetName ()+ " : " +amount); Balance-=amount; System.out.println (Thread.CurrentThread (). GetName ()+ ":" + "Balance is" +balance); } } }}
Summarize:
Synchronous code blocks and synchronous methods all indicate that an object needs to be locked before execution of a piece of code, the synchronization code block needs to be specified, and the synchronization method defaults to this.
Java synchronization code block and synchronization method