Java multi-thread series -- mutex lock ReentrantLock of "JUC lock" 02

Source: Internet
Author: User

ReentrantLock: ReentrantLock Is A reentrant mutex lock. It is also called an exclusive lock ". As the name suggests, the ReentrantLock can only be held by one thread lock at the same time point. reentrant means that the ReentrantLock can be obtained multiple times by a single thread. ReentrantLock is divided into "fair lock" and "unfair lock ". Their difference lies in the fairness of the lock acquisition mechanism. The "Lock" is used to protect competing resources and prevent multiple threads from simultaneously operating on the thread, reentrantLock can only be acquired by one thread at the same time point (when a thread gets the "Lock", other threads must wait ); reentraantLock manages and acquires all threads of the lock through a FIFO waiting queue. Under the "fair lock" mechanism, the thread queues to obtain locks. When the "unfair lock" is available, the lock is obtained no matter whether it is at the beginning of the queue or not. Copy the code in the ReentrantLock function list // create a ReentrantLock. The default value is "unfair lock ". ReentrantLock () // create the ReentrantLock policy of fair. True indicates a fair lock, and false indicates a non-fair lock. ReentrantLock (boolean fair) // queries the number of times the current thread keeps the lock. Int getHoldCount () // returns the thread that currently owns the lock. If the lock is not owned by any thread, null is returned. Protected Thread getOwner () // returns a collection that may be waiting for the Thread to obtain the lock. Protected Collection <Thread> getQueuedThreads () // returns the estimated number of threads waiting to obtain the lock. Int getQueueLength () // returns a collection containing the threads that may be waiting for the given conditions related to this lock. Protected Collection <Thread> getWaitingThreads (Condition condition) // returns the number of threads waiting for the given conditions related to the lock. Int getWaitQueueLength (Condition condition) // queries whether the given thread is waiting to obtain the lock. Boolean hasQueuedThread (Thread thread) // query whether some threads are waiting to obtain the lock. Boolean hasQueuedThreads () // queries whether some threads are waiting for the given conditions related to the lock. Boolean hasWaiters (Condition condition) // if it is a "fair lock", true is returned; otherwise, false is returned. Boolean isFair () // query whether the current thread maintains this lock. Boolean isHeldByCurrentThread () // queries whether the lock is maintained by any thread. Boolean isLocked () // obtain the lock. Void lock () // obtain the lock if the current thread is not interrupted. Void lockInterruptibly () // return the Condition instance used with this Lock instance. Condition newCondition () // This lock is obtained only when the lock is not kept by another thread during the call. Boolean tryLock () // If the lock is not kept by another thread within the specified wait time and the current thread is not interrupted, the lock is obtained. Boolean tryLock (long timeout, TimeUnit unit) // attempts to release this lock. Void unlock () Copy code ReentrantLock example by comparing "Example 1" and "Example 2", we can clearly understand the role of lock and unlock Example 1 copy code 1 import java. util. concurrent. locks. lock; 2 import java. util. concurrent. locks. reentrantLock; 3 4 // LockTest1.java 5 // warehouse 6 class Depot {7 private int size; // the actual number of warehouses 8 private Lock; // exclusive lock 9 10 public Depot () {11 this. size = 0; 12 this. lock = new ReentrantLock (); 13} 14 15 public void produce (int val) {16 lock. Lock (); 17 try {18 size + = val; 19 System. out. printf ("% s produce (% d) --> size = % d \ n", 20 Thread. currentThread (). getName (), val, size); 21} finally {22 lock. unlock (); 23} 24} 25 26 public void consume (int val) {27 lock. lock (); 28 try {29 size-= val; 30 System. out. printf ("% s consume (% d) <-- size = % d \ n", 31 Thread. currentThread (). getName (), val, size); 32} finally {33 lock. unlock (); 34} 35} 36}; 37 38 // generated Producer 39 class Producer {40 private Depot depot; 41 42 public Producer (Depot depot) {43 this. depot = depot; 44} 45 46 // consumption product: Create a New thread to produce the product to the warehouse. 47 public void produce (final int val) {48 new Thread () {49 public void run () {50 depot. produce (val); 51} 52 }. start (); 53} 54} 55 56 // consumer 57 class Customer {58 private Depot depot; 59 60 public Customer (Depot depot) {61 this. depot = depot; 62} 63 64 // consumption product: Create a New thread to consume the product from the warehouse. 65 public void consume (final int val) {66 new Thread () {67 public void run () {68 depot. consume (val); 69} 70 }. start (); 71} 72} 73 74 public class LockTest1 {75 public static void main (String [] args) {76 Depot mDepot = new Depot (); 77 Producer mPro = new Producer (mDepot); 78 Customer mCus = new Customer (mDepot); 79 80 mPro. produce (60); 81 mPro. produce (120); 82 mCus. consume (90); 83 mCus. consume (150); 84 O. produce (110); 85} 86} copy the code running result: Thread-0 produce (60) --> size = 60Thread-1 produce (120) --> size = 180Thread-3 consume (150) <-- size = 30Thread-2 consume (90) <-- size =-60Thread-4 produce (110) --> size = 50 result analysis: (01) Depot is a repository. By using produce (), you can produce goods in the warehouse and consume the goods in the warehouse through consume. Achieve mutually exclusive access to the warehouse through exclusive lock: Before operating (production/consumption) the warehouse, the warehouse will be locked through lock (), and then through unlock () after the operation () unlock. (02) Producer is a Producer class. You can call the produce () function in Producer to create a thread to generate products in the repository. (03) Customer is a consumer class. Call the consume () function in Customer to create a product in the thread consumption warehouse. (04) in the main thread, we will create a producer mPro and a consumer mCus. They produce/consume products in the warehouse respectively. Based on the production/consumption quantity in main, the final remaining products in the warehouse should be 50. The running result is as expected! This model has two problems: (01) In reality, the warehouse capacity cannot be negative. However, the warehouse capacity in this model can be negative, which is in conflict with reality! (02) In reality, the warehouse capacity is limited. However, the capacity in this model is indeed unlimited! We will discuss how to solve these two problems. Now let's take a look at Example 2. By comparing "Example 1" and "Example 2", we can better understand the usage of lock () and unlock. Example 2 Copy code 1 import java. util. concurrent. locks. lock; 2 import java. util. concurrent. locks. reentrantLock; 3 4 // LockTest2.java 5 // warehouse 6 class Depot {7 private int size; // the actual number of warehouses 8 private Lock; // exclusive lock 9 10 public Depot () {11 this. size = 0; 12 this. lock = new ReentrantLock (); 13} 14 15 public void produce (int val) {16 // lock. lock (); 17 // try {18 size + = val; 19 System. out. printf ("% s produce (% d) --> Size = % d \ n ", 20 Thread. currentThread (). getName (), val, size); 21 //} catch (InterruptedException e) {22 //} finally {23 // lock. unlock (); 24 //} 25} 26 27 public void consume (int val) {28 // lock. lock (); 29 // try {30 size-= val; 31 System. out. printf ("% s consume (% d) <-- size = % d \ n", 32 Thread. currentThread (). getName (), val, size); 33 //} finally {34 // lock. unlock (); 35 //} 36} 37}; 38 39 // producer 40 class Producer {41 private Depot depot; 42 43 public Producer (Depot depot) {44 this. depot = depot; 45} 46 47 // consumption product: Create a New thread to produce the product to the warehouse. 48 public void produce (final int val) {49 new Thread () {50 public void run () {51 depot. produce (val); 52} 53 }. start (); 54} 55} 56 57 // consumer 58 class Customer {59 private Depot depot; 60 61 public Customer (Depot depot) {62 this. depot = depot; 63} 64 65 // consumption product: Create a New thread to consume the product from the warehouse. 66 public void consume (final int val) {67 new Thread () {68 public void run () {69 depot. consume (val); 70} 71 }. start (); 72} 73} 74 75 public class LockTest2 {76 public static void main (String [] args) {77 Depot mDepot = new Depot (); 78 Producer mPro = new Producer (mDepot); 79 Customer mCus = new Customer (mDepot); 80 81 mPro. produce (60); 82 mPro. produce (120); 83 mCus. consume (90); 84 mCus. consume (150); 85 O. produce (110); 86} 87} copy the code (one time) running result: Thread-0 produce (60) --> size =-60Thread-4 produce (110) --> size = 50Thread-2 consume (90) <-- size =-60Thread-1 produce (120) --> size =-60Thread-3 consume (150) <-- size =-60 result description: "Example 2" removes the lock Based on "Example 1. In "Example 2", the final remaining products in the repository are-60, rather than the expected 50. The reason is that we have not implemented mutex access to the repository. Example 3 in Example 3, we solve two problems in Example 1 through Condition: "The warehouse capacity cannot be negative" and "the warehouse capacity is limited ". To solve this problem, use Condition. Condition needs to be used together with Lock: Through the await () method in Condition, it can cause thread blocking [similar to wait ()]; through the signal () method of Condition, can wake up a thread [similar to running y ()]. Copy code 1 import java. util. concurrent. locks. lock; 2 import java. util. concurrent. locks. reentrantLock; 3 import java. util. concurrent. locks. condition; 4 5 // LockTest3.java 6 // repository 7 class Depot {8 private int capacity; // repository capacity 9 private int size; // The actual number of warehouses is 10 private Lock lock; // exclusive Lock 11 private Condition fullCondtion; // production Condition 12 private Condition emptyCondtion; // consumption Condition 13 14 public Depot (int capaci Ty) {15 this. capacity = capacity; 16 this. size = 0; 17 this. lock = new ReentrantLock (); 18 this. fullCondtion = lock. newCondition (); 19 this. emptyCondtion = lock. newCondition (); 20} 21 22 public void produce (int val) {23 lock. lock (); 24 try {25 // left indicates "quantity to be produced" (there may be too much production, more production is required) 26 int left = val; 27 while (left> 0) {28 // when the inventory is full, wait for the "consumer" to consume the product. 29 while (size> = capacity) 30 fullCondtion. await (); 31 // obtain the "actual production quantity" (that is, the new quantity in the inventory) 32 // If "inventory" + "quantity to be produced"> "total capacity", "actual increment" = "total capacity"-"current capacity ". (Fill the warehouse at this time) 33 // otherwise "actual increment" = "quantity to be produced" 34 int inc = (size + left)> capacity? (Capacity-size): left; 35 size + = inc; 36 left-= inc; 37 System. out. printf ("% s produce (% 3d) --> left = % 3d, inc = % 3d, size = % 3d \ n", 38 Thread. currentThread (). getName (), val, left, inc, size); 39 // The notification "consumer" can be consumed. 40 emptyCondtion. signal (); 41} 42} catch (InterruptedException e) {43} finally {44 lock. unlock (); 45} 46} 47 48 public void consume (int val) {49 lock. lock (); 50 try {51 // left indicates "number of customers to consume" (it is possible that the consumption amount is too large and the inventory is insufficient. Additional consumption is required) 52 int left = val; 53 while (left> 0) {54 // when the inventory is 0, wait for the "producer" to produce the product. 55 while (size <= 0) 56 emptyCondtion. await (); 57 // obtain the "quantity actually consumed" (that is, the quantity actually reduced in the inventory) 58 // If "inventory" <"quantity to be consumed by the customer ", then "actual consumption" = "inventory"; 59 // otherwise, "actual consumption" = "number of customers to consume ". 60 int dec = (size <left )? Size: left; 61 size-= dec; 62 left-= dec; 63 System. out. printf ("% s consume (% 3d) <-- left = % 3d, dec = % 3d, size = % 3d \ n", 64 Thread. currentThread (). getName (), val, left, dec, size); 65 fullCondtion. signal (); 66} 67} catch (InterruptedException e) {68} finally {69 lock. unlock (); 70} 71} 72 73 public String toString () {74 return "capacity:" + capacity + ", actual size:" + size; 75} 76 }; 77 78 // Production 79 class Producer {80 private Depot depot; 81 82 public Producer (Depot depot) {83 this. depot = depot; 84} 85 86 // consumption product: Create a New thread to produce the product to the warehouse. 87 public void produce (final int val) {88 new Thread () {89 public void run () {90 depot. produce (val); 91} 92 }. start (); 93} 94} 95 96 // consumer 97 class Customer {98 private Depot depot; 99 100 public Customer (Depot depot) {101 this. depot = depot; 102} 103 104 // consumption product: Create a thread to consume the product from the warehouse. 105 public void consume (final int val) {106 new Thread () {107 public void run () {108 depot. consume (val); 109} 110 }. start (); 111} 112} 113 114 public class LockTest3 {115 public static void main (String [] args) {116 Depot mDepot = new Depot (100 ); 117 Producer mPro = new Producer (mDepot); 118 Customer mCus = new Customer (mDepot); 119 120 mPro. produce (60); 121 mPro. produce (120); 122 mCus. consume (90); 123 mCus. consume (150); 124 mPro. produce (110); 125} 126} copy code

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.