Multi-thread programming learning 4 (use of Lock), multi-thread programming lock

Source: Internet
Author: User

Multi-thread programming learning 4 (use of Lock), multi-thread programming lock
I. Preface

This article will introduce the use of Lock objects in Java 5, which can also achieve the synchronization effect, and is more convenient and flexible in use, mainly including the use of the ReentrantLock class and the use of the ReentrantReadWriteLock class.

Ii. Use the ReentrantLock class

1,In java multithreading, you can use the synchronized keyword to achieve synchronization and mutual exclusion between threads. However, the newly added ReentrantLock in JDK can achieve the same effect and be more powerful in expansion, for example, it has functions such as sniffing lock and multi-channel branch notifications, and is more flexible in use than synchronized.

2,The thread that calls the lock. lock () code holds the "Object monitor", that is, the lock holds some Object locks and relies on instances of this class.

Public class MyService {private Lock lock = new ReentrantLock (); public void testMethod () {lock. lock (); for (int I = 0; I <5; I ++) {System. out. println (Thread. currentThread (). getName () + (I + 1);} lock. unlock ();}}View Code

3,The key words synchronized can be combined with the wait () and Y ()/notifyAll () methods to implement the waiting/notification mode. The ReentrantLock class can also implement the same function, but the Condition object must be used.

The wait () method in the Object class is equivalent to the wait (long timeout) method in the await () method in the Condition class and the await (long time, TimeUnit unit) method in the Condition class) the notify () method in the method Object class is equivalent to the policyall () method in the signal () method Object class in the Condition class and the signalAll () method in the Condition class () method public class Myservice {private Lock lock = new ReentrantLock (); private Condition condition = lock. newCondition (); // wait for public void waitMethod () {try {lock. lock (); System. out. println ("A"); condition. await (); // The await wait method of the called Condition also needs to be in the synchronous method; otherwise, an error is returned. out. println ("B");} catch (InterruptedException e) {e. printStackTrace ();} finally {lock. unlock () ;}// wake up public void signal () {try {lock. lock (); System. out. println ("Wake up now... "); condition. signal ();} finally {lock. unlock ();}}}View Code

4,Multiple Condition objects are used to implement selective notifications between threads.

Public class MyService {private Lock lock = new ReentrantLock (); // you can call a specified type of threads by defining multiple conditions to implement selective notifications, this is // convenient form for controlling part of thread behavior private Condition conditionA = lock. newCondition (); private Condition conditionB = lock. newCondition (); public void awaitA () {try {lock. lock (); System. out. println ("awaitA begin"); conditionA. await (); System. out. println ("awaitA end");} catch (InterruptedException e) {e. printStackTrace ();} finally {lock. unlock () ;}} public void awaitB () {try {lock. lock (); System. out. println ("awaitB begin"); conditionB. await (); System. out. println ("awaitB end");} catch (InterruptedException e) {e. printStackTrace ();} finally {lock. unlock () ;}} public void signalA () {try {lock. lock (); System. out. println ("Wake up awaitA now"); conditionA. signalAll ();} finally {lock. unlock () ;}} public void signalB () {try {lock. lock (); System. out. println ("Wake up awaitB now"); conditionB. signalAll ();} finally {lock. unlock ();}}}View Codepublic class Run {public static void main (String [] args) throws InterruptedException {MyService myService = new MyService (); Thread threadA = new Thread () {@ Override public void run () {super. run (); myService. awaitA () ;}}; Thread threadB = new Thread () {@ Override public void run () {super. run (); myService. awaitB () ;}}; threadA. start (); threadB. start (); Thread. sleep (1000); myService. signalA (); Thread. sleep (1000); myService. signalB ();}}View Code

5,Fair lock and unfair lock

Fair lock: the lock Acquisition sequence of a thread is allocated according to the locking sequence of the thread, that is, the first-come-first-served FIFO order. Unfair lock: A lock preemption mechanism is used to obtain the lock at random. Unlike a fair lock, the first lock is not necessarily obtained first, this method may cause some threads to fail to get the lock, and the result is unfair. Public class Service {private Lock lock; public Service (boolean isFair) {// create a fair Lock (true) and an unfair lock (false) in this way) lock = new ReentrantLock (isFair);} public void methodA () {try {lock. lock (); System. out. println (Thread. currentThread (). getName () + "running");} finally {lock. unlock ();}}}View Codepublic class Run {public static void main (String [] args) {final Service service = new Service (true); Runnable runnable = new Runnable () {@ Override public void run () {service. methodA () ;}}; Thread [] threads = new Thread [10]; for (int I = 0; I <10; I ++) {threads [I] = new Thread (runnable); threads [I]. setName ("Thread" + (I + 1); threads [I]. start ();}}}View Code

 6,ReentrantLock common methods

(1) int getHoldCount () queries the number of times the current thread holds the lock, that is, the number of times the lock method is called in the thread.

(2) int getQueueLength () returns the estimated number of threads waiting for the Lock. For example, if there are five threads and one thread is occupying the Lock during execution, 4 is returned when this method is called. This value is only an estimated number, because the number of threads may change dynamically while traversing the internal data structure. This method is used to monitor the system status and is not used for synchronization control.

(3) int getWaitQueueLength (Condition condition) returns the number of threads waiting for the given Condition related to this lock. For example, there are five threads, if every thread executes the await () method of the same condition object, the value returned by calling this method is 5.

Public class Service {private ReentrantLock lock = new ReentrantLock (); private Condition condition = lock. newCondition (); public void methodA () {try {lock. lock (); System. out. println ("A getHoldCount number of times lock is called =>" + lock. getHoldCount (); Thread. sleep (1, 2000); System. out. println ("A getQueueLength is waiting for the number of threads =>" + lock. getQueueLength (); condition. await ();} catch (InterruptedException e) {e. printStackTrace ();} finally {lock. unlock () ;}}// test the getWaitQueueLength method public Integer methodC () {try {lock. lock (); return lock. getWaitQueueLength (condition);} finally {lock. unlock ();}}}View Codepublic class Run {public static void main (String [] args) throws InterruptedException {Service service = new Service (); Runnable runnable = new Runnable () {@ Override public void run () {service. methodA () ;}}; Thread [] threads = new Thread [5]; for (int I = 0; I <5; I ++) {threads [I] = new Thread (runnable); threads [I]. start ();} Thread. sleep (1, 1000); System. out. println ("await () threads that execute the same Condition object include:" + service. methodC ());}}View Code

(4) boolean hasQueuedThread (Thread thread) queries whether the specified Thread is waiting to obtain the lock.

(5) boolean hasQueuedThreads () queries whether a thread is waiting to obtain the lock.

(6) boolean hasWaiters (Condition condition) queries whether a thread is waiting for the condition Condition related to this lock.

(7) boolean isFair () determines whether it is a fair lock.

(8) boolean isHelpByCurrentThread () checks whether the current thread keeps this lock.

(9) boolean isLocked () checks whether the lock is maintained by any thread.

 

(10) void lockInterruptibly () gets locked if the current thread is not interrupted. If the thread has been interrupted, an exception occurs.

(11) boolean tryLock () is obtained only when the lock is not locked by another thread during the call.

(12) boolean tryLock (long timeout, TimeUnit unit) gets the lock if the lock is not kept by another thread within the specified waiting time and the current thread is not interrupted.

Public class Service {private ReentrantLock lock = new ReentrantLock (); private Condition condition = lock. newCondition (); // test lockInterruptibly public void methodA () {try {lock. lockInterruptibly (); System. out. println ("methodA =" "+ Thread. currentThread (). getName ();} catch (InterruptedException e) {e. printStackTrace ();} finally {if (lock. isHeldByCurrentThread () {// if the current thread remains locked, the lock is released. unlock () ;}}// test tryLock public void methodB () {if (lock. tryLock () {System. out. println (Thread. currentThread (). getName () + "get lock");} else {System. out. println (Thread. currentThread (). getName () + "Unlocked ");}}}View Codepublic class Run {public static void main (String [] args) throws InterruptedException {Service service = new Service (); Runnable runnable = new Runnable () {@ Override public void run () {service. methodA (); service. methodB () ;}}; Thread threadA = new Thread (runnable); threadA. setName ("A"); threadA. start (); Thread. sleep (1000); Thread threadB = new Thread (runnable); threadB. setName ("B"); threadB. start (); threadB. interrupt ();}}View Code

 

(13) lock. awaitUninterruptibly (): This thread will not be interrupted until other threads call the signal () or signalAll () method.

(14) lock. awaitUntil (Date date): This thread will remain asleep:

  • It is interrupted
  • Other threads call the singal () or signalAll () method on this condition.
  • The specified date has arrived.
3. Using the ReentrantReadWriteLock class RenntrantLock has a completely exclusive effect, that is, only one thread is executing the task after the RenntrantLock. lock () method. This ensures the thread security of instance variables, but the efficiency is very low, because even if there is no written content in the lock, it can be read only after the lock is released. Therefore, JDK provides a read/write lock ReentrantReadWriteLock class, which can accelerate the running efficiency. ReentrantReadWriteLock has two locks: one is a read-related lock, also known as a shared lock; the other is a write-related lock, also known as an exclusive lock. That is, multiple read locks are not mutually exclusive. Read locks and write locks are mutually exclusive. Write locks and write locks are mutually exclusive. When there is no Thread for write operations, read locks can be obtained from multiple threads that perform read operations. The write operation can be performed only after the Thread obtains the write lock. That is, multiple threads can read data at the same time, but only one Thread can write data at the same time. Read is not mutually exclusive:Public class Read {private ReentrantReadWriteLock lock = new ReentrantReadWriteLock (); public void read () {try {lock. readLock (). lock (); System. out. println (Thread. currentThread (). getName () + "reading" + System. currentTimeMillis (); Thread. sleep (100);} catch (InterruptedException e) {e. printStackTrace ();} finally {lock. readLock (). unlock ();}}}View Codepublic class Run {public static void main (String [] args) {Read read Read = new Read (); Runnable runnable = new Runnable () {@ Override public void run () {read. read () ;}}; Thread [] threads = new Thread [10]; for (int I = 0; I <10; I ++) {threads [I] = new Thread (runnable); threads [I]. start (); // The result shows that almost all threads enter the lock () method at the same time. // read the code that does not conflict with each other to improve the program running efficiency, allow // Code following the lock () method executed by multiple threads at the same time }}}View Code Write mutex:Public class Write {private ReentrantReadWriteLock lock = new ReentrantReadWriteLock (); public void write () {try {lock. writeLock (). lock (); System. out. println (Thread. currentThread (). getName () + "writing" + System. currentTimeMillis (); Thread. sleep (2000);} catch (InterruptedException e) {e. printStackTrace ();} finally {lock. writeLock (). unlock ();}}}View Codepublic class Run {public static void main (String [] args) {Write write = new Write (); Runnable runnable = new Runnable () {@ Override public void run () {write. write () ;}}; Thread [] threads = new Thread [10]; for (int I = 0; I <10; I ++) {threads [I] = new Thread (runnable); threads [I]. start (); // The result shows that all threads run every two seconds. The write and write operations are mutually exclusive and the threads run simultaneously }}}View Code

 

In addition, the write and read/write operations are mutually exclusive. In short, as long as there is a "write" operation, it is mutually exclusive!

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.