Java introduces Lock and producer-consumer issues
Feb 09, 2021 pm 05:43 PMFree learning recommendation: java basic tutorial
Lock lock and producer-consumer issues
- Traditional Synchronized lock
- Lock lock
- The difference between Synchronized and lock lock
- Traditional producer and consumer issues
- Lock version of producer and consumer issues
- Condition to achieve precise notification wake-up
Traditional Synchronized lock
Implement a basic ticket sales example:
/* 真正的多線程開發(fā),公司中的開發(fā),降低耦合性 線程就是一個單獨的資源類,沒有任何附屬的操作 1.屬性,方法 ?*?*/public?class?SaleTicketDemo1?{ ????public?static?void?main(String[]?args)?{ ????????//并發(fā),多個線程操作同一個資源類,把資源類丟入線程 ????????Ticket?ticket=new?Ticket(); ????????//Runnable借口是一個FunationalInterface函數(shù)式接口,接口可以new,jdk1.8以后,lamda表達式()->{代碼} ????????new?Thread(()->{ ????????????for(int?i=0;i{ ????????????for(int?i=0;i0){ ????????????System.out.println(Thread.currentThread().getName()+"賣出了"+(number--)+"票,剩余"+number); ????????} ????}}
Note that lambda expressions are used here. For detailed descriptions of lambda expressions, see Java Basics-Lambda Expressions
This is to use traditional synchronized to achieve concurrency. The essence of synchronized is queues and locks. It's like queuing up in a cafeteria. If there is no queue, it will be chaotic. Only when the service to one person is completed can the other person receive the service.
Lock
As mentioned before, the JVM provides the synchronized keyword to achieve synchronous access to variables and use wait and notify to implement inter-thread communication. After jdk1.5, JAVA provides the Lock class to implement the same functions as synchronized, and also provides Condition to display inter-thread communication.
The Lock class is a function provided by the Java class. The rich API makes the synchronization function of the Lock class more powerful than synchronized synchronization.
In the java.util. Concurrent package, there are 3 interfaces, Condition and lock (standard lock). ReadWriteLock lock (read-write lock)
Lock implementation provides a wider range of locking operations than can be obtained using synchronized methods and statements. They allow for more flexible structuring, may have completely different properties, and can support multiple associated object Conditions.
Lock?l?=?...;?l.lock();?try?{?//?access?the?resource?protected?by?this?lock?}?finally?{?l.unlock();?}
lock() means locking, unlock() means unlocking
Explained in the JDK official document
All have been Known implementation class:
ReentrantLock reentrant lock
ReentrantReadWriteLock.ReadLock read lock
ReentrantReadWriteLock.writeLock write lock
Let’s talk about the ReentrantLock implementation class first:
ReentrantLock underlying source code constructor
Fair lock: very fair, first come, first served. But the problem is that if a 3s and a 3h process arrive, 3h comes first, then 3s waits for 3h, which is actually not good.
Unfair lock: Very unfair, you can jump the queue (default)
We will explain it in detail later.
How to use, lock before use, unlock after use
//lock lock trilogy
//1.new ReentranLock() ;Construction
//2.Lock.lock();Lock
//3.finally();Unlock
public?class?SaleTicketDemo2?{ public?static?void?main(String[]?args)?{ //并發(fā),多個線程操作同一個資源類,把資源類丟入線程 Ticket?ticket=new?Ticket(); //Runnable借口是一個FunationalInterface函數(shù)式接口,接口可以new,jdk1.8以后,lamda表達式()->{代碼} new?Thread(()->{for(int?i=0;i{for(int?i=0;i{for(int?i=0;i0){ System.out.println(Thread.currentThread().getName()+"賣出了"+(number--)+"票,剩余"+number); } }?catch?(Exception?e)?{ //?TODO:?handle?exception }finally{ lock.unlock(); } }}
The difference between Synchronized and lock lock
1.synchronized is a built-in java keyword, lock is a Java class
2.synchronized cannot determine the status of acquiring the lock, lock can determine whether the lock has been acquired
3.synchronized will automatically To release the lock (a–), the lock must be released manually! If the lock is not released, it will lead to deadlock
4. Synchronized thread 1 (obtaining the lock, blocking), thread 2 (waiting, waiting stupidly)
lock.tryLock() tries to acquire the lock, which may not always happen Wait
5. Synchronized reentrant lock, uninterruptible, unfair lock. Lock, reentrant lock, can judge the lock, fair and unfair can be set by yourself (can be set by yourself)
6. synchronized is suitable for a small amount of code synchronization problems, lock lock is suitable for locking a large amount of synchronized code
synchornized lock object and synchronized code block method
Traditional producer and consumer issues
Traditional producers and consumers are based on the wait, notify method and synchronized key of the Object class Words are used to achieve this.
During interviews, it is very common to hand-write producer and consumer code.
Classic questions in the interview written test:
Singleton mode sorting algorithm producer-consumer deadlock
Synchronized version of producer-consumer problem
Communication problem between threads: producer Waiting for wake-up with consumer issues, notification wake-up
Threads alternately execute A B to operate the same variable number=0
A num 1
B num-1
Note: is locked In the method, the idea of ????execution is to judge and wait for business notification
package?testConcurrent;/* 線程之間的通信問題:生產(chǎn)者和消費者問題????等待喚醒,通知喚醒 線程交替執(zhí)行?A?B?操作同一個變量number=0 A?num+1 B?num-1 ?*?*/public?class?A?{ public?static?void?main(String[]?args)?{ Data?data?=new?Data(); new?Thread(()->{ for(int?i=0;i{ for(int?i=0;i"+number); //通知其他線程,我+1完畢了 this.notify(); } //-1 public?synchronized?void?decrement()?throws?InterruptedException{ if(number==0){ //等待 this.wait(); } number--; System.out.println(Thread.currentThread().getName()+"=>"+number); //通知其他線程,我-1完畢了 this.notify(); }}
As shown in the figure, the required functions can basically be achieved, but problems will still occur. If I try again at this time Adding two threads, then
new?Thread(()->{ for(int?i=0;i{ for(int?i=0;i<p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/052/4011c6e510a595c0afc39326e031cf33-4.png" class="lazy" alt="Java introduces Lock and producer-consumer issues"><br> 這里結(jié)果中出現(xiàn)了2,輸出結(jié)果出現(xiàn)了問題。為什么呢?<br> 為什么if判斷會出現(xiàn)問題:<br> if判斷只判斷一次。因為if判斷了之后,就已經(jīng)進入了代碼的等待那一行,這時,在wait下的線程可能有多個,甚至包括生產(chǎn)者和消費者。有可能某個生產(chǎn)者執(zhí)行完了之后,喚醒的是另一個生產(chǎn)者。</p><p>在我們的官方文檔中就給出了解釋</p><pre class="brush:php;toolbar:false">public?final?void?wait(long?timeout) ????????????????throws?InterruptedException
導致當前線程等待,直到另一個線程調(diào)用此對象的notify()方法或notifyAll()方法,或指定的時間已過。
線程也可以喚醒,而不會被通知,中斷或超時,即所謂的虛假喚醒 。 雖然這在實踐中很少會發(fā)生,但應用程序必須通過測試應該使線程被喚醒的條件來防范,并且如果條件不滿足則繼續(xù)等待。 換句話說,等待應該總是出現(xiàn)在循環(huán)中,就像這樣:
?synchronized?(obj)?{ ?????????while?(<condition>) ?????????????obj.wait(timeout); ?????????...?//?Perform?action?appropriate?to?condition ?????}</condition>
注意點:防止虛假喚醒問題。
我們代碼中用的是if判斷,而應該用while判斷
package?testConcurrent;/* 線程之間的通信問題:生產(chǎn)者和消費者問題????等待喚醒,通知喚醒 線程交替執(zhí)行?A?B?操作同一個變量number=0 A?num+1 B?num-1 ?*?*/public?class?A?{ ????public?static?void?main(String[]?args)?{ ????????Data?data?=new?Data(); ????????new?Thread(()->{ ????????????for(int?i=0;i{ ????????????for(int?i=0;i{ ????????????for(int?i=0;i{ ????????????for(int?i=0;i"+number); ????????//通知其他線程,我+1完畢了 ????????this.notify(); ????} ????//-1 ????public?synchronized?void?decrement()?throws?InterruptedException{ ????????while(number==0){ ????????????//等待 ????????????this.wait(); ????????} ????????number--; ????????System.out.println(Thread.currentThread().getName()+"=>"+number); ????????//通知其他線程,我-1完畢了 ????????this.notify(); ????}}
Lock版的生產(chǎn)者和消費者問題
在synchronized版本中,我們使用了wait和notify來實現(xiàn)線程之間的同步
在lock中,
此時synchronized被lock替換了,那么wait和notify用什么來替換呢?
我們在官方文檔java.util.concurrent.locks 中,找到Lock類,然后在底部找到了
Condition newCondition()
返回一個新Condition綁定到該實例Lock實例。
在等待條件之前,鎖必須由當前線程保持。 呼叫Condition.await()將在等待之前將原子釋放鎖,并在等待返回之前重新獲取鎖。
然后我們再來了解Condition類
Condition 將 Object 監(jiān)視器方法(wait、notify 和 notifyAll)分解成截然不同的對象,以便通過將這些對象與任意 Lock 實現(xiàn)組合使用,為每個對象提供多個等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監(jiān)視器方法的使用。
一個Condition實例本質(zhì)上綁定到一個鎖。 要獲得特定Condition實例的Condition實例,請使用其newCondition()方法。
我們可以看到,使用的時候new一個Condition對象。然后用await替代wait,signal替換notify
代碼實現(xiàn)
//判斷等待+業(yè)務+通知
class?Data2{ //數(shù)字。資源類 private?int?number=0; Lock?lock=new?ReentrantLock(); Condition?condition=lock.newCondition(); //+1 public?void?increment()?throws?InterruptedException{ try?{ lock.lock(); //業(yè)務代碼 while(number!=0){ //等待 condition.await(); } number++; System.out.println(Thread.currentThread().getName()+"=>"+number); condition.signalAll(); //通知 }?catch?(Exception?e)?{ //?TODO:?handle?exception }finally{ lock.unlock(); } } //-1 public?void?decrement()?throws?InterruptedException{ try?{ lock.lock(); //業(yè)務代碼 while(number!=1){ //等待 condition.await(); } number--; System.out.println(Thread.currentThread().getName()+"=>"+number); condition.signalAll(); //通知 }?catch?(Exception?e)?{ //?TODO:?handle?exception }finally{ lock.unlock(); } } }
注意:主函數(shù)部分于最上面的代碼一樣。
這時候雖然說是正確的,但是它是一個隨機分布的狀態(tài),現(xiàn)在我們希望它有序執(zhí)行,即A執(zhí)行完了執(zhí)行B,B執(zhí)行C,C完了執(zhí)行D。即精準通知。
Condition實現(xiàn)精準通知喚醒
Condition實現(xiàn)精準的通知和喚醒
我們構(gòu)造三個線程,要求A執(zhí)行完了執(zhí)行B,B執(zhí)行完了執(zhí)行C,C執(zhí)行完了執(zhí)行D.
代碼思想:
//加多個監(jiān)視器,通過監(jiān)視器來判斷喚醒的是哪一個人
//設置多個同步監(jiān)視器,每個監(jiān)視器監(jiān)視一個線程
//實例:生產(chǎn)線,下單->支付->交易->物流
package?testConcurrent;import?java.util.concurrent.locks.Condition;import?java.util.concurrent.locks.Lock;import?java.util.concurrent.locks.ReentrantLock;/* A執(zhí)行完調(diào)用B,B執(zhí)行完調(diào)用C,C執(zhí)行完調(diào)用A ?*?*/public?class?C?{ ????public?static?void?main(String[]?args)?{ ????????Data3?data=new?Data3(); ????????new?Thread(()->{ ????????????for(int?i=0;i{ ????????????for(int?i=0;i{ ????????????for(int?i=0;i支付->交易->物流 ????private?Condition?condition1=lock.newCondition(); ????private?Condition?condition2=lock.newCondition(); ????private?Condition?condition3=lock.newCondition(); ????private?int?number=1;???????//1A?2B?3C ????public?void?printA(){ ????????lock.lock(); ????????try?{ ????????????//業(yè)務,判斷->執(zhí)行->通知 ????????????while(number!=1){ ????????????????//等待 ????????????????condition1.await(); ????????????} ????????????System.out.println(Thread.currentThread().getName()+"=>AAAAAAA"); ????????????//喚醒,喚醒指定的人,B ????????????number=2;???????????//精準喚醒 ????????????condition2.signal(); ???????????? ????????}?catch?(Exception?e)?{ ????????????//?TODO:?handle?exception ????????}finally{ ????????????lock.unlock(); ????????} ????}??? ????public?void?printB(){ ????????lock.lock(); ????????try?{ ????????????//業(yè)務,判斷->執(zhí)行->通知 ????????????while(number!=2){ ????????????????//等待 ????????????????condition2.await(); ????????????} ????????????System.out.println(Thread.currentThread().getName()+"=>BBBBBBB"); ????????????//喚醒,喚醒指定的人,C ????????????number=3;???????????//精準喚醒 ????????????condition3.signal(); ???????????? ????????}?catch?(Exception?e)?{ ????????????//?TODO:?handle?exception ????????}finally{ ????????????lock.unlock(); ????????} ????} ????public?void?printC(){ ????????lock.lock(); ????????try?{ ????????????//業(yè)務,判斷->執(zhí)行->通知 ????????????while(number!=3){ ????????????????//等待 ????????????????condition3.await(); ????????????} ????????????System.out.println(Thread.currentThread().getName()+"=>CCCCCCC"); ????????????//喚醒,喚醒指定的人,A ????????????number=1;???????????//精準喚醒 ????????????condition1.signal(); ???????????? ????????}?catch?(Exception?e)?{ ????????????//?TODO:?handle?exception ????????}finally{ ????????????lock.unlock(); ????????} ????}}
相關(guān)學習推薦:java基礎(chǔ)
The above is the detailed content of Java introduces Lock and producer-consumer issues. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

The settings.json file is located in the user-level or workspace-level path and is used to customize VSCode settings. 1. User-level path: Windows is C:\Users\\AppData\Roaming\Code\User\settings.json, macOS is /Users//Library/ApplicationSupport/Code/User/settings.json, Linux is /home//.config/Code/User/settings.json; 2. Workspace-level path: .vscode/settings in the project root directory

itertools.combinations is used to generate all non-repetitive combinations (order irrelevant) that selects a specified number of elements from the iterable object. Its usage includes: 1. Select 2 element combinations from the list, such as ('A','B'), ('A','C'), etc., to avoid repeated order; 2. Take 3 character combinations of strings, such as "abc" and "abd", which are suitable for subsequence generation; 3. Find the combinations where the sum of two numbers is equal to the target value, such as 1 5=6, simplify the double loop logic; the difference between combinations and arrangement lies in whether the order is important, combinations regard AB and BA as the same, while permutations are regarded as different;

To correctly handle JDBC transactions, you must first turn off the automatic commit mode, then perform multiple operations, and finally commit or rollback according to the results; 1. Call conn.setAutoCommit(false) to start the transaction; 2. Execute multiple SQL operations, such as INSERT and UPDATE; 3. Call conn.commit() if all operations are successful, and call conn.rollback() if an exception occurs to ensure data consistency; at the same time, try-with-resources should be used to manage resources, properly handle exceptions and close connections to avoid connection leakage; in addition, it is recommended to use connection pools and set save points to achieve partial rollback, and keep transactions as short as possible to improve performance.

DependencyInjection(DI)isadesignpatternwhereobjectsreceivedependenciesexternally,promotingloosecouplingandeasiertestingthroughconstructor,setter,orfieldinjection.2.SpringFrameworkusesannotationslike@Component,@Service,and@AutowiredwithJava-basedconfi

fixture is a function used to provide preset environment or data for tests. 1. Use the @pytest.fixture decorator to define fixture; 2. Inject fixture in parameter form in the test function; 3. Execute setup before yield, and then teardown; 4. Control scope through scope parameters, such as function, module, etc.; 5. Place the shared fixture in conftest.py to achieve cross-file sharing, thereby improving the maintainability and reusability of tests.

java.lang.OutOfMemoryError: Javaheapspace indicates insufficient heap memory, and needs to check the processing of large objects, memory leaks and heap settings, and locate and optimize the code through the heap dump analysis tool; 2. Metaspace errors are common in dynamic class generation or hot deployment due to excessive class metadata, and MaxMetaspaceSize should be restricted and class loading should be optimized; 3. Unabletocreatenewnativethread due to exhausting system thread resources, it is necessary to check the number of threads, use thread pools, and adjust the stack size; 4. GCoverheadlimitexceeded means that GC is frequent but has less recycling, and GC logs should be analyzed and optimized.

Use classes in the java.time package to replace the old Date and Calendar classes; 2. Get the current date and time through LocalDate, LocalDateTime and LocalTime; 3. Create a specific date and time using the of() method; 4. Use the plus/minus method to immutably increase and decrease the time; 5. Use ZonedDateTime and ZoneId to process the time zone; 6. Format and parse date strings through DateTimeFormatter; 7. Use Instant to be compatible with the old date types when necessary; date processing in modern Java should give priority to using java.timeAPI, which provides clear, immutable and linear

TomonitoraJavaapplicationwithPrometheusandGrafana,firstinstrumenttheappusingMicrometerbyaddingmicrometer-registry-prometheusandSpringBootActuatordependencies,thenexposethe/actuator/prometheusendpointviaconfigurationinapplication.yml.2.SetupPrometheus
