Detailed explanation of the use of mutex Reentrantlock classes in Java multithreaded programming _java

Source: Internet
Author: User
Tags int size mutex

0. About Mutual exclusion locks

A mutex is a lock that can be held by at most one thread at a time. Before jdk1.5, we usually use the synchronized mechanism to control the access of multiple threads to shared resources. Now, Lock provides a wider range of locking operations than the synchronized mechanism, the main differences between lock and synchronized mechanisms:
The synchronized mechanism provides access to an implicit monitor lock associated with each object and forces all lock acquisition and release to appear in a block structure, which must be released in reverse order when multiple locks are acquired. The synchronized mechanism is implicit in the release of the lock, and the lock is freed as long as the thread running code is outside the synchronized block range. The lock mechanism must explicitly invoke the Unlock () method of the lock object to release the lock, which provides the possibility of acquiring and releasing the lock not appearing in the same block structure, and releasing the lock in a more free order.

1. Reentrantlock Introduction
Reentrantlock is a reentrant mutex, also known as an "exclusive lock."
As the name suggests, Reentrantlock locks can only be held by a single thread lock at one point in time, and reentrant means that reentrantlock locks can be acquired multiple times by individual threads.
Reentrantlock is divided into "fair lock" and "unjust lock". Their differences are reflected in the fairness of the mechanism for acquiring locks. "Lock" is to protect competitive resources, prevent multiple threads to manipulate threads simultaneously error, reentrantlock at the same point in time can only be obtained by one thread (when a thread acquires "lock", other threads must wait) Reentraantlock is managed by a FIFO wait queue to acquire all threads of the lock. Under the "fair lock" mechanism, threads queue to acquire locks, and "unjust locks" acquire locks when the lock is in a accessible state, regardless of whether they are at the beginning of the queue.

Reentrantlock Function List

Create a Reentrantlock, default is "unjust lock". Reentrantlock ()///Create policy is fair's reentrantlock.
Fair to TRUE indicates a fair lock, and fair to false is a fair lock.
Reentrantlock (Boolean Fair)//query the number of times the current thread holds this lock.
int Getholdcount ()//returns the thread that currently owns this lock, and returns NULL if the lock is not owned by any thread.
Protected thread GetOwner ()//Returns a collection that contains threads that may be waiting to acquire this lock.
Protected collection<thread> getqueuedthreads ()//Returns the number of thread estimates that are waiting to get this lock.
int getqueuelength ()//Returns a collection that contains those threads that may be waiting for a given condition associated with this lock.
Protected collection<thread> getwaitingthreads (Condition Condition)//Returns the thread estimate waiting for the given condition associated with this lock.
int Getwaitqueuelength (Condition Condition)//query whether a given thread is waiting to acquire this lock.
Boolean hasqueuedthread (thread thread)//query If some threads are waiting to acquire this lock.
Boolean hasqueuedthreads ()//query whether some threads are waiting for the given condition associated with this lock.
Boolean haswaiters (Condition Condition)//If the fair lock returns True, False is returned.
Boolean Isfair ()//queries whether the current thread maintains this lock.
Boolean isheldbycurrentthread ()//query Whether this lock is persisted by any thread.
Boolean islocked ()//Acquire lock.
void lock ()//If the current thread is not interrupted, acquire the lock.
void lockinterruptibly ()//Returns the Condition instance used with this Lock instance. Condition newcondition ()// The lock is acquired only if the lock is not persisted by another thread at the time of the call.
Boolean trylock ()//If the lock is not persisted by another thread within the given wait time, and the current thread is not interrupted, the lock is acquired.
Boolean Trylock (long timeout, timeunit unit)//attempting to release this lock.

 void Unlock ()

2. Reentrantlock example
by comparing "Example 1" and "Example 2", we can clearly understand the role of lock and unlock
2.1 Example 1

Import Java.util.concurrent.locks.Lock;

Import Java.util.concurrent.locks.ReentrantLock;  Locktest1.java//Warehouse class Depot {private int size;  The actual number of warehouses private lock lock;
  Exclusive lock Public Depot () {this.size = 0;
 This.lock = new Reentrantlock ();
  public void produce (int val) {lock.lock ();
   try {size = val;
  System.out.printf ("%s produce (%d)--> size=%d\n", Thread.CurrentThread (). GetName (), Val, size);
  finally {Lock.unlock ();
  } public void consume (int val) {lock.lock ();
   try {size = val;
  System.out.printf ("%s consume (%d) <--size=%d\n", Thread.CurrentThread (). GetName (), Val, size);
  finally {Lock.unlock (); 

}
 }
};

 Producer class Producer {private Depot Depot;
 Public Producer (Depot Depot) {this.depot = Depot;
 //Consumer Products: Create a new thread to produce the product in the warehouse.
   public void produce (final int val) {new Thread () {public void run () {depot.produce (val);
 }}.start (); }//Consumer class Customer {private Depot Depot
 Public Customer (Depot Depot) {this.depot = Depot;
 //Consumer Products: Create a new thread to consume the product from the warehouse.
   public void consume (final int val) {new Thread () {public void run () {Depot.consume (val);
 }}.start ();
  } public class LockTest1 {public static void main (string[] args) {Depot mdepot = new Depot ();
  Producer Mpro = new Producer (mdepot);

  Customer MCUs = new Customer (mdepot);
  Mpro.produce (60);
  Mpro.produce (120);
  Mcus.consume (90);
  Mcus.consume (150);
 Mpro.produce (110);

 }
}

Run Result:

Thread-0 produce--> size=60 Thread-1 Produce (a)--> size=180 Thread-3 consume
(m) <--size=30<
C3/>thread-2 consume (<--size=-60 Thread-4 produce
()-->

Results Analysis:
(1) Depot is a warehouse. Through the produce () to the warehouse to produce goods, through the consume () can consume the goods in the warehouse. Mutually exclusive access to the warehouse through exclusive lock locks: The warehouse is locked (by lock) before the goods in the warehouse (production/consumption), and then unlocked by unlock () after the operation.
(2) Producer is a producer class. Call the produce () function in producer to create a new thread to produce the product in the warehouse.
(3) Customer is consumer class. Call the consume () function in customer to create a new product in a thread consumption warehouse.
(4) in the main thread main, we will create a new 1 producer Mpro, while the new 1 consumer MCUs. They produce/consume products separately from the warehouse.
According to the production/consumption quantity in Main, the final remaining product of the warehouse should be 50. The results of the operation are in line with our expectations!
There are two problems with this model:
(1) In reality, the capacity of warehouses cannot be negative. However, the warehouse capacity in this model can be negative, which is inconsistent with the reality!
(2) In reality, the capacity of the warehouse is limited. However, there is really no limit to the capacity in this model!
We'll talk a little bit about how to solve these two problems. Now, let's look at a simple example 2, and by comparing "Example 1" and "Example 2", we can get a clearer picture of the purpose of lock (), Unlock ().

2.2 Example 2

Import Java.util.concurrent.locks.Lock;

Import Java.util.concurrent.locks.ReentrantLock;    Locktest2.java//Warehouse class Depot {private int size;    The actual number of warehouses private lock lock;
    Exclusive lock Public Depot () {this.size = 0;
  This.lock = new Reentrantlock ();
      public void produce (int val) {//Lock.lock ();//try {size + = Val;
System.out.printf ("%s produce (%d)--> size=%d\n", Thread.CurrentThread (). GetName (), Val, size); The catch (Interruptedexception e) {//} finally {//Lock.unlock ();//}} public void consume (int v
      AL) {//Lock.lock ();//try {size = val;
System.out.printf ("%s consume (%d) <--size=%d\n", Thread.CurrentThread (). GetName (), Val, size);

finally {//Lock.unlock ();//}}};

  Producer class Producer {private Depot Depot;
  Public Producer (Depot Depot) {this.depot = Depot;
  //Consumer Products: Create a new thread to produce the product in the warehouse. public void produce (final int val) {
    New Thread () {public void run () {depot.produce (val);
  }}.start ();

  }//Consumer class Customer {private Depot Depot;
  Public Customer (Depot Depot) {this.depot = Depot;
  //Consumer Products: Create a new thread to consume the product from the warehouse.
      public void consume (final int val) {new Thread () {public void run () {Depot.consume (val);
  }}.start ();
    } public class LockTest2 {public static void main (string[] args) {Depot mdepot = new Depot ();
    Producer Mpro = new Producer (mdepot);

    Customer MCUs = new Customer (mdepot);
    Mpro.produce (60);
    Mpro.produce (120);
    Mcus.consume (90);
    Mcus.consume (150);
  Mpro.produce (110);


 }
}

(one time) run result:

Thread-0 produce--> size=-60 Thread-4 Produce (a)--> size=50 Thread-2 consume
(m) <--size=-60<
C3/>thread-1 produce--> size=-60
Thread-3 consume (<--)

Results show:
Example 2 removes the lock lock on the basis of "Example 1". In "Example 2", the final remaining product in the warehouse is-60, not the 50 we expect. The reason is that we did not implement mutually exclusive access to the warehouse.

2.3 Example 3
In Example 3, we solved the two problems in "Example 1" by condition: "The capacity of the warehouse cannot be negative" and "the capacity of the warehouse is limited".
The problem is solved by condition. Condition is required to be used in conjunction with Lock: the await () method in condition allows the thread to block [similar to wait ()], and the condition signal () method to make the wake thread [similar to notify ()].

Import Java.util.concurrent.locks.Lock;
Import Java.util.concurrent.locks.ReentrantLock;

Import java.util.concurrent.locks.Condition;  Locktest3.java//Warehouse class Depot {private int capacity;    The capacity of the warehouse private int size;    The actual number of warehouses private lock lock;      Exclusive lock private Condition fullcondtion;    Production conditions private Condition emptycondtion;
    Consumption conditions public Depot (int capacity) {this.capacity = capacity;
    this.size = 0;
    This.lock = new Reentrantlock ();
    This.fullcondtion = Lock.newcondition ();
  This.emptycondtion = Lock.newcondition ();
    public void produce (int val) {lock.lock ();
      try {//left indicates the quantity you want to produce (it is possible to produce too much, you need to produce more) int left = Val;
        while (Left > 0) {//Inventory is full, wait for "consumer" consumer product.
        while (size >= capacity) fullcondtion.await (); Get "Actual production quantity" (that is, the quantity added to the inventory)//if "inventory" + "quantity wanted to produce" > "Total Capacity", then "actual increment" = "Total Capacity"-"current capacity". (At this point fill the warehouse)//otherwise "actual increment" = "Quantity wanted to produce" int inc = (size+left) >capAcity?
        (capacity-size): left;
        Size + + Inc;
        Left-= Inc; System.out.printf ("%s produce (%3d)--> left=%3d, inc=%3d, size=%3d\n", Thread.CurrentThread (). GetName (), V
        AL, left, Inc., size);
        Notice that "consumers" can be consumed.
      Emptycondtion.signal ();
    The catch (Interruptedexception e) {} finally {Lock.unlock ();
    } public void consume (int val) {lock.lock ();
      try {//left indicates "customer wants to consume quantity" (it is possible that consumption is too large, inventory is insufficient, need more this consumption) int left = Val;
        while (Left > 0) {//Inventory is 0 o'clock, wait for "producer" to produce the product.
        while (size <= 0) emptycondtion.await ();
        Get the "quantity of actual consumption" (that is, the amount actually reduced in inventory)//if "stock" < "the quantity that the customer wants to consume", "actual consumption" = "inventory";//otherwise, "actual consumption" = "Quantity to be consumed by the customer". int dec = (size<left)?
        Size:left;
        size = Dec;
        Left-= Dec; System.out.printf ("%s consume (%3d) <--left=%3d, dec=%3d, size=%3d\n", Thread.CurrentThread (). GetName (), V
        Al, left, Dec, size); FullcoNdtion.signal ();
    The catch (Interruptedexception e) {} finally {Lock.unlock ();
  } public String toString () {return "Capacity:" +capacity+ ", Actual size:" +size;

}
};

  Producer class Producer {private Depot Depot;
  Public Producer (Depot Depot) {this.depot = Depot;
  //Consumer Products: Create a new thread to produce the product in the warehouse.
      public void produce (final int val) {new Thread () {public void run () {depot.produce (val);
  }}.start ();

  }//Consumer class Customer {private Depot Depot;
  Public Customer (Depot Depot) {this.depot = Depot;
  //Consumer Products: Create a new thread to consume the product from the warehouse.
      public void consume (final int val) {new Thread () {public void run () {Depot.consume (val);
  }}.start ();
    } public class LockTest3 {public static void main (string[] args) {Depot mdepot = new Depot (100);
    Producer Mpro = new Producer (mdepot);

    Customer MCUs = new Customer (mdepot);
    Mpro.produce (60);
    Mpro.produce (120); MCus.consume (90);
    Mcus.consume (150);
  Mpro.produce (110);

 }
}

(one time) run result:

Thread-0 produce--> left= 0, inc=, size= Thread-1 Produce ()--> left=, inc=,
size=100
T Hread-2 consume (<--left= 0, dec=, size= Thread-3 consume
() <--left=140, dec=, size= 0
Thr Ead-4 produce--> left=, inc=100, size=100 Thread-3 consume
() <--left=, dec=100, size= 0
thre ad-4 produce--> left= 0, inc=, size= Thread-3 consume (i) <--left=, dec=
0
Thread -1 Produce (-->) left= 0, inc=, size=
0 Thread-3 consume () <--left= 50

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.