簡體   English   中英

Java線程同步意外輸出

[英]Java Threads synchronization unexpected output

我正在為OCPJP考試而學習,並且很難理解線程。 特別是,我在下面列出了該程序。 當我運行該程序時,得到以下輸出,這使我感到困惑。

Inside push method...
Inside push method now sleeping...
Exit from main()
Inside push method stopped sleeping...
Exiting push method...
Pushed: true
Popped: 2008
Inside push method...
Inside push method now sleeping...
Inside push method stopped sleeping...
Exiting push method...
Pushed: true
Inside push method...
Inside push method now sleeping...
Inside push method stopped sleeping...
Exiting push method...
Pushed: true
Popped: 2008
Inside push method...
Inside push method now sleeping...
Popped: 2008

讓我明白的是輸出的最后一行。 api表示在調用睡眠時線程不會失去對任何監視器/鎖的所有權。 以下內容如何:

Inside push method now sleeping...
Popped: 2008
自從我們進入同步方法push()的那一刻起就可能發生,push()具有監視/鎖定功能,為什么我們可以在push()處於休眠狀態時執行pop()方法? 我需要幫助,可能有人請給出一個易於理解的解釋嗎?

 class StackImpl { //(1) private Object[] stackArray; private int topOfStack; public StackImpl(int capacity){ stackArray = new Object[capacity]; topOfStack = -1; } // public boolean push(Object element){ //(2a) non-synchronized public synchronized boolean push(Object element){ //(2b) synchronized if(isFull()) return false; System.out.println("Inside push method..."); ++topOfStack; try{ System.out.println("Inside push method now sleeping..."); Thread.sleep(10000); System.out.println("Inside push method stopped sleeping...");} catch(Exception e){} //(3) Sleep a little stackArray[topOfStack] = element; System.out.println("Exiting push method..."); return true; } //public Object pop(){ //(4a) non-synchronized public synchronized Object pop(){ //(4b) synchronized if(isEmpty()) return null; Object obj = stackArray[topOfStack]; stackArray[topOfStack] = null; try{Thread.sleep(1000);}catch(Exception e){} //(5) Sleep a little topOfStack--; return obj; } public boolean isEmpty(){return topOfStack < 0;} public boolean isFull(){return topOfStack >= stackArray.length - 1;} } public class Mutex{ public static void main(String[] args) throws InterruptedException { final StackImpl stack = new StackImpl(20); //(6) Shared by the threads (new Thread("Pusher"){ //(7) Thread no. 1 public void run(){ for(;;){ System.out.println("Pushed: " + stack.push(2008)); } } }).start(); // make sure Thread no.1 goes first Thread.sleep(2000); (new Thread("Popper"){ //(8) Thread no.2 public void run(){ for(;;){ System.out.println("Popped: " + stack.pop()); } } }).start(); System.out.println("Exit from main()"); } } 

輸出是一致的,但並不直接與堆棧上的操作相對應(對printlnpop / push的單獨調用不是原子的)。 在Java中,不要在Thread.sleep(n)釋放監視器上的鎖是正確的(但是Object.wait()並非如此)。

要查看實際訂單,您可以修改放入堆棧的內容...

final  StackImpl stack = new StackImpl(20);                     //(6) Shared by the threads


(new Thread("Pusher"){                                          //(7) Thread no. 1

    public void run(){

    int i = 0;

        for(;;){
            System.out.println("Pushed: " + stack.push(i++));
        }
    }
}).start();

現在,您應該能夠看到哪個推送對應於哪個彈出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM