高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析
生活随笔
收集整理的這篇文章主要介紹了
高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 概述
- jstack或者可視化工具檢測是否死鎖(沒有)
- 原因分析
概述
高并發(fā)編程-線程通信_使用wait和notify進(jìn)行線程間的通信 - 遺留問題
我們看到了 應(yīng)用卡住了 。。。。 懷疑是不是死鎖呢? (其實(shí)沒有)
jstack或者可視化工具檢測是否死鎖(沒有)
C:\Users\Mr.Yang>E:E:\>cd E:\Program Files\Java\jdk1.8.0_161\binE:\Program Files\Java\jdk1.8.0_161\bin>jps 1504 MultiProduceConsumerDemoE:\Program Files\Java\jdk1.8.0_161\bin>jstack 1504 2019-10-01 00:44:23 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.161-b12 mixed mode):"DestroyJavaVM" #15 prio=5 os_prio=0 tid=0x0000000002983800 nid=0x3348 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Thread-3" #14 prio=5 os_prio=0 tid=0x0000000019fa5000 nid=0x3af0 in Object.wait() [0x000000001abff000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000078b682768> (a java.lang.Object)at java.lang.Object.wait(Object.java:502)at com.artisan.test.MultiProduceConsumerDemo.consume(MultiProduceConsumerDemo.java:42)- locked <0x000000078b682768> (a java.lang.Object)at com.artisan.test.MultiProduceConsumerDemo$2.run(MultiProduceConsumerDemo.java:63)"Thread-2" #13 prio=5 os_prio=0 tid=0x0000000019fa4000 nid=0x9e4 in Object.wait() [0x000000001aaff000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000078b682768> (a java.lang.Object)at java.lang.Object.wait(Object.java:502)at com.artisan.test.MultiProduceConsumerDemo.consume(MultiProduceConsumerDemo.java:42)- locked <0x000000078b682768> (a java.lang.Object)at com.artisan.test.MultiProduceConsumerDemo$2.run(MultiProduceConsumerDemo.java:63)"Thread-1" #12 prio=5 os_prio=0 tid=0x0000000019fa0000 nid=0x37cc in Object.wait() [0x000000001a9ff000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000078b682768> (a java.lang.Object)at java.lang.Object.wait(Object.java:502)at com.artisan.test.MultiProduceConsumerDemo.produce(MultiProduceConsumerDemo.java:20)- locked <0x000000078b682768> (a java.lang.Object)at com.artisan.test.MultiProduceConsumerDemo$1.run(MultiProduceConsumerDemo.java:55)"Thread-0" #11 prio=5 os_prio=0 tid=0x0000000019f9f800 nid=0x1bd4 in Object.wait() [0x000000001a8fe000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000078b682768> (a java.lang.Object)at java.lang.Object.wait(Object.java:502)at com.artisan.test.MultiProduceConsumerDemo.produce(MultiProduceConsumerDemo.java:20)- locked <0x000000078b682768> (a java.lang.Object)at com.artisan.test.MultiProduceConsumerDemo$1.run(MultiProduceConsumerDemo.java:55)"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x0000000019d2f800 nid=0x3ba4 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x0000000019ca3800 nid=0x37e4 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x0000000019c54800 nid=0x2db0 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000000019c50800 nid=0x37bc waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000000019c2e000 nid=0x2ed4 runnable [0x000000001a2fe000]java.lang.Thread.State: RUNNABLEat java.net.SocketInputStream.socketRead0(Native Method)at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)at java.net.SocketInputStream.read(SocketInputStream.java:171)at java.net.SocketInputStream.read(SocketInputStream.java:141)at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)- locked <0x000000078b5dad50> (a java.io.InputStreamReader)at java.io.InputStreamReader.read(InputStreamReader.java:184)at java.io.BufferedReader.fill(BufferedReader.java:161)at java.io.BufferedReader.readLine(BufferedReader.java:324)- locked <0x000000078b5dad50> (a java.io.InputStreamReader)at java.io.BufferedReader.readLine(BufferedReader.java:389)at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000018860000 nid=0x34f8 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000019c08800 nid=0x1514 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001883a000 nid=0x22c in Object.wait() [0x0000000019b9e000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000078b408ec0> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)- locked <0x000000078b408ec0> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000002a73800 nid=0x29bc in Object.wait() [0x0000000019a9f000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000078b406b68> (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:502)at java.lang.ref.Reference.tryHandlePending(Reference.java:191)- locked <0x000000078b406b68> (a java.lang.ref.Reference$Lock)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)"VM Thread" os_prio=2 tid=0x0000000018818000 nid=0x381c runnable"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002998000 nid=0x3024 runnable"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x000000000299a000 nid=0x229c runnable"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000000000299b800 nid=0x2bbc runnable"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000299d000 nid=0x255c runnable"VM Periodic Task Thread" os_prio=2 tid=0x0000000019d67800 nid=0x1c5c waiting on conditionJNI global references: 334E:\Program Files\Java\jdk1.8.0_161\bin>可以看到 并沒有死鎖的發(fā)生
或者 使用 jvisualvm 、 jmc 工具來看下都行
(jmc截圖)
并且可以看到4個(gè)線程 均是 WAITING 狀態(tài)
(jmc截圖)
原因分析
為了方便觀察,我們改造下,給線程起個(gè)名
package com.artisan.test;import java.util.stream.Stream;public class MultiProduceConsumerDemo {// 對象監(jiān)視器-鎖private final Object LOCK = new Object();// 是否生產(chǎn)出數(shù)據(jù)的標(biāo)識private boolean isProduced = false;// volatile 確保可見性, 假設(shè) i 就是生產(chǎn)者生產(chǎn)的數(shù)據(jù)private volatile int i = 0 ;public void produce(){synchronized (LOCK){System.out.println(Thread.currentThread() + " GOT LOCK " + isProduced);String msg = isProduced ? "已生產(chǎn)貨物" : "沒有貨物可搬運(yùn)";if (isProduced){try {System.out.println(Thread.currentThread() + " wait becauseof " + msg );LOCK.wait();} catch (InterruptedException e) {e.printStackTrace();}}else{i++;System.out.println(Thread.currentThread() + " Produce:" + i);LOCK.notify();isProduced = true;}}}public void consume(){// 加鎖synchronized (LOCK){System.out.println(Thread.currentThread() + " GOT LOCK " + isProduced);String msg = isProduced ? "已生產(chǎn)貨物" : "沒有貨物可搬運(yùn)";if (isProduced){System.out.println(Thread.currentThread() + " Consume:" + i);LOCK.notify();isProduced = false;}else{try {System.out.println(Thread.currentThread() + " wait becauseof " + msg);LOCK.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {MultiProduceConsumerDemo produceConsumerDemo = new MultiProduceConsumerDemo();Stream.of("P1","P2").forEach(n-> new Thread(n){@Overridepublic void run() {while(true) produceConsumerDemo.produce();}}.start());Stream.of("C1","C2").forEach(n->new Thread(n){@Overridepublic void run() {while(true) produceConsumerDemo.consume();}}.start());} }運(yùn)行下 ,可以看到程序并沒有持續(xù)運(yùn)行,而是假死了…
(每次運(yùn)行的結(jié)果都有可能不一樣,這里我們以這次的運(yùn)行結(jié)果來分析下)
逐步分析下:
生產(chǎn)者的代碼
消費(fèi)者代碼
那如何解決呢? 下篇博文我們一起來探討下
總結(jié)
以上是生活随笔為你收集整理的高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高并发编程-线程通信_使用wait和no
- 下一篇: 高并发编程-使用wait和notifyA