0
我正在學習OCPJP考試,並且很難理解線程。特別是,我在下面列出了這個程序。當我運行這個程序時,我得到了下面的輸出,它讓我感到困惑。Java線程同步意外輸出
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()");
}
}
謝謝賈森,我很感激幫助,我會給你的解決方案一個鏡頭,看看我能否更好地理解它。我會回來告訴你,如果我做或不做。 – user1279734 2014-10-11 05:36:11
重要的一點是調用'println'是在調用'push'或'pop'後發生的,但是你不能說對'println'的併發調用之間的順序,因爲你只在那些內部同步兩個電話。 – Jason 2014-10-11 05:51:02