In Java5, a lock object is specially provided, which can be used to easily block resources and control concurrent access to competing resources. These contents are mainly concentrated under the java.util.concurrent.locks package, and there are three important Interfaces Condition, Lock, ReadWriteLock.
Condition:
Condition decomposes the Object monitor methods (wait, notify, and notifyAll) into distinct objects to provide multiple wait-sets per object by combining these objects with any Lock implementation.
Lock:
The Lock implementation provides a wider range of locking operations than is available with synchronized methods and statements.
ReadWriteLock:
ReadWriteLock maintains a pair of related locks, one for read-only operations and one for write operations.
Regarding the introduction of locks, there are a lot of explanations in the API documentation, which is very annoying to read. It is easier to understand by looking at an example and then reading the documentation.
package cn.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * * @author Lin Jiqin * @version 1.0 2013-7-25 上午10:33:37 */ public class LockTest { public static void main(String[] args) { LockTest test = new LockTest(); // Create a concurrent access account MyCount myCount = test.new MyCount("95599200901215522", 10000 ); // Create a lock object Lock lock = new ReentrantLock(); // Create a thread pool ExecutorService pool = Executors.newCachedThreadPool() ; // Create some concurrent access users, a credit card, deposit and withdraw, so lively User u1 = test. new User("Zhang San", myCount, -4000 , lock); User u2 = test. new User("Zhang San's father", myCount, 6000 , lock); User u3 = test. new User("Zhang San's younger brother", myCount, -8000 , lock); User u4 = test.new User("Zhang San", myCount, 800 , lock); // Execute the operations of each user in the thread pool pool.execute(u1); pool.execute(u2); pool.execute(u3); pool.execute(u4); // Close the thread pool pool.shutdown(); } /** * Credit card users */ class User implements Runnable { private String name; // User name private MyCount myCount; // The account to be operated private int iocash; // The amount of the operation, of course, there are positive and negative points private Lock myLock; // Execute the operation Desired lock object User(String name, MyCount myCount, int iocash, Lock myLock) { this .name = name; this .myCount = myCount; this .iocash = iocash; this .myLock = myLock; } public void run() { String string; if(iocash>0){ string ="deposit" ; }else{ string = "Withdrawal" ; } // Get the lock myLock.lock(); // Execute the cash business System.out.println(name + "operating" + myCount + "account, " + string + "the amount is " + iocash + ", the current amount is " + myCount.getCash()); myCount.setCash(myCount.getCash() + iocash); System.out.println(name + "operation" + myCount + "account successful, "+ string + "amount is " + iocash + ", current amount is " + myCount.getCash()); System.out.println( "============" ); // Release the lock, otherwise other threads have no chance to execute myLock.unlock(); } } /** * Credit card account, free to overdraft */ class MyCount { private String oid; // account private int cash; // account balance MyCount(String oid, int cash) { this .oid = oid; this .cash = cash; } public String getOid() { return oid; } public void setOid(String oid) { this.oid = oid; } public int getCash() { return cash; } public void setCash(int cash) { this.cash = cash; } @Override public String toString() { return "MyCount{" + "账号='" + oid + '\'' + ", 余额=" + cash + '}'; } } }
Zhang San is operating the MyCount{account='95599200901215522', balance=10000} account, the withdrawal amount is -4000 , and the current amount is 10000 Zhang San operates MyCount{account ='95599200901215522', balance=6000}The account is successful, the withdrawal amount is -4000 , and the current amount is 6000 ============ Zhang San's brother is operating MyCount{account = '95599200901215522', balance=6000} account, the withdrawal amount is -8000 , the current amount is 6000 Zhang San and his brother operated MyCount{account ='95599200901215522', balance=-2000} account successfully, the withdrawal amount is -8000, and the current amount is -2000 =========== Zhang Santa is operating MyCount{Account ='95599200901215522', balance=-2000}, the deposit amount is 6000, the current amount is -2000 Zhang Santa is operating MyCount{ Account number='95599200901215522', balance=4000 }Account is successful, deposit amount is 6000, current amount is 4000 ============ Zhang San is operating MyCount{Account ='95599200901215522', balance=4000 } Account, deposit amount is 800, current amount is 4000 Zhang San operates MyCount{Account ='95599200901215522', Balance=4800 }The account is successful, the deposit amount is 800, and the current amount is 4800 ============
As you can see from the above output, using the lock object is too convenient, much clearer than using the lock directly on an unwitting object.
But it must be noted that after acquiring the lock object, the lock should be released as soon as possible after use, so that other threads waiting for the lock have the opportunity to execute.