Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use API under Lock Mechanism in Java concurrent programming

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces how to use API under the Lock mechanism in Java concurrent programming. It is very detailed and has a certain reference value. Interested friends must read it!

1. Lock architecture 1. Introduction to basic interfaces.

Two widely used basic API:ReentrantLock classes and Condition interfaces are involved in Lock locking-related structures, and the basic relationships are as follows:

Lock interface

One of the root interfaces of resource locking in Java concurrent programming, which defines several basic methods for the use of resource locks.

ReentrantLock class

Implement the reentrant lock of Lock interface, that is, if a thread acquires the lock of the current instance and enters the task method, when the thread does not release the lock, it can enter the task method again, which is characterized by mutual exclusion, that is, only one thread enters the task at the same time.

Condition interface

The Condition interface describes the condition variables that may be associated with the lock, providing more powerful functions, such as Conditon can implement multi-channel notification and selective notification on the thread wait / notification mechanism.

2. Use cases

Production and consumption pattern

The writer thread adds data to the container, the reader thread gets the data from the container, and if the container is empty, the reader thread waits.

Public class LockAPI01 {private static Lock lock = new ReentrantLock (); private static Condition condition1 = lock.newCondition (); private static Condition condition2 = lock.newCondition (); public static void main (String [] args) throws Exception {List dataList = new ArrayList (); ReadList readList = new ReadList (dataList); WriteList writeList = new WriteList (dataList); new Thread (readList). Start (); TimeUnit.SECONDS.sleep (2) New Thread (writeList) .start ();} / read data thread static class ReadList implements Runnable {private List dataList; public ReadList (List dataList) {this.dataList = dataList;} @ Override public void run () {lock.lock () Try {if (dataList.size ()! = 2) {System.out.println ("Read wait..."); condition1.await ();} System.out.println ("ReadList WakeUp...") For (String element:dataList) {System.out.println ("ReadList:" + element);} condition2.signalAll ();} catch (InterruptedException e) {e.fillInStackTrace ();} finally {lock.unlock () Static class WriteList implements Runnable {private List dataList; public WriteList (List dataList) {this.dataList = dataList;} @ Override public void run () {lock.lock (); try {dataList.add ("Java") DataList.add ("C++"); condition1.signalAll (); System.out.println ("Write over..."); condition2.await (); System.out.println ("Write WakeUp...");} catch (InterruptedException e) {e.fillInStackTrace () } finally {lock.unlock ();}

This production and consumption pattern is very similar to the ordering scene in life, where the user places an order, notifies the cook to cook, and notifies the food delivery when the cooking is finished.

Sequential execution mode

Since thread execution can notify each other, it can also be based on this mechanism to achieve sequential thread execution, the basic idea: after the completion of one thread execution, wake up the next thread conditionally.

Public class LockAPI02 {public static void main (String [] args) {PrintInfo printInfo = new PrintInfo (); ExecutorService service = Executors.newFixedThreadPool (3); service.execute (new PrintA (printInfo)); service.execute (new PrintB (printInfo)); service.execute (new PrintC (printInfo));} class PrintA implements Runnable {private PrintInfo printInfo; public PrintA (PrintInfo printInfo) {this.printInfo = printInfo } @ Override public void run () {printInfo.printA ();}} class PrintB implements Runnable {private PrintInfo printInfo; public PrintB (PrintInfo printInfo) {this.printInfo = printInfo;} @ Override public void run () {printInfo.printB ();}} class PrintC implements Runnable {private PrintInfo printInfo; public PrintC (PrintInfo printInfo) {this.printInfo = printInfo } @ Override public void run () {printInfo.printC ();}} class PrintInfo {/ / controls the next thread of execution private String info = "A"; private ReentrantLock lock = new ReentrantLock (); / / three threads, three control conditions Condition conditionA = lock.newCondition (); Condition conditionB = lock.newCondition (); Condition conditionC = lock.newCondition () Public void printA () {try {lock.lock (); while (! info.equals ("A")) {conditionA.await ();} System.out.print ("A"); info = "B"; conditionB.signalAll ();} catch (InterruptedException e) {e.printStackTrace () } finally {lock.unlock ();}} public void printB () {try {lock.lock (); while (! info.equals ("B")) {conditionB.await ();} System.out.print ("B"); info = "C" ConditionC.signalAll ();} catch (InterruptedException e) {e.printStackTrace ();} finally {lock.unlock ();}} public void printC () {try {lock.lock (); while (! info.equals ("C")) {conditionC.await () } System.out.print ("C"); info = "A"; conditionA.signalAll ();} catch (InterruptedException e) {e.printStackTrace ();} finally {lock.unlock ();}

This case often appears in multi-threaded interview questions. The basic idea of how to realize the sequential printing of ABC is the thread-based waiting notification mechanism, but there are many ways to achieve it, and the above is only one of them.

2. Read-write locking mechanism 1. Introduction to basic API

The exclusive nature of reentrant locks determines that performance will cause bottlenecks. In order to improve performance problems, there is another read-write locking mechanism in JDK. Read-write locks maintain a shared read lock and an exclusive write lock. In actual development, there are still many read scenarios, so read-write locks can improve concurrency.

There are two basic API:ReadWriteLock interfaces and ReentrantReadWriteLock implementation classes in the read-write lock related structure, and the basic relationship is as follows:

ReadWriteLock

Two basic methods are provided: readLock acquires read-mechanism locks and writeLock acquires write-mechanism locks.

ReentrantReadWriteLock

The specific implementation of the interface ReadWriteLock, features: based on the read lock, other threads can read operations, based on the write lock, other threads read and write operations are prohibited.

2. Use cases

Read-write separation mode

Through the read-write locking mechanism, the read-write locking mechanism is verified by writing and reading data to the data container Map respectively.

Public class LockAPI03 {public static void main (String [] args) throws Exception {DataMap dataMap = new DataMap (); Thread read = new Thread (new GetRun (dataMap)); Thread write = new Thread (new PutRun (dataMap)); write.start (); Thread.sleep (2000); read.start ();} class GetRun implements Runnable {private DataMap dataMap Public GetRun (DataMap dataMap) {this.dataMap = dataMap;} @ Override public void run () {System.out.println ("GetRun:" + dataMap.get ("myKey");}} class PutRun implements Runnable {private DataMap dataMap; public PutRun (DataMap dataMap) {this.dataMap = dataMap;} @ Override public void run () {dataMap.put ("myKey", "myValue") }} class DataMap {Map dataMap = new HashMap (); ReadWriteLock rwLock = new ReentrantReadWriteLock (); Lock readLock = rwLock.readLock (); Lock writeLock = rwLock.writeLock (); / / read data public String get (String key) {readLock.lock (); try {return dataMap.get (key);} finally {readLock.unlock () }} / / write data public void put (String key,String value) {writeLock.lock (); try {dataMap.put (key,value); System.out.println ("execute write end..."); Thread.sleep (10000);} catch (Exception e) {System.out.println ("Exception...") } finally {writeLock.unlock ();}

Description: when the put method has been sleeping, the read method cannot be executed because of the exclusive nature of the write lock.

III. Basic tool class

Introduction to LockSupport

LockSupprot defines a set of public static methods that provide the most basic thread blocking and wake-up work

Yes.

Basic method

Park (): the current thread is blocked, the current thread is interrupted or the unpark method is called, and the park () method returns

Park (Object blocker): the function is the same as park (), passing in Object objects to record blocking objects that cause thread blocking, so as to facilitate troubleshooting.

ParkNanos (long nanos): blocks the current thread within the specified time nanos, and returns a timeout

Unpark (Thread thread): wakes up a specified thread in a blocking state

Code case

This process is very common on shopping APP. If you give up when you are ready to pay, there will be a payment invalidation. You can come back to pay at any time during the payment expiration period, and you need to reselect the payment item when it expires.

Public class LockAPI04 {public static void main (String [] args) throws Exception {OrderPay orderPay = new OrderPay ("UnPaid"); Thread orderThread = new Thread (orderPay); orderThread.start (); Thread.sleep (3000); orderPay.changeState ("Pay"); LockSupport.unpark (orderThread);} class OrderPay implements Runnable {/ / payment status private String orderState Public OrderPay (String orderState) {this.orderState = orderState;} public synchronized void changeState (String orderState) {this.orderState = orderState;} @ Override public void run () {if (orderState.equals ("UnPaid")) {System.out.println ("order to be paid..." + orderState); LockSupport.park (orderState) } System.out.println ("orderState=" + orderState); System.out.println ("order is ready for shipment...");}}

In this paper, the waiting notification mechanism is realized based on the thread state control by park and unpark in LockSupport.

Source code address GitHub address https://github.com/cicadasmile/java-base-parentGitEE address https://gitee.com/cicadasmile/java-base-parent is all the contents of this article entitled "how to use API under the Lock mechanism in Java concurrent programming". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report