簡體   English   中英

有關線程同步的幾個問題

[英]a few questions about thread synchronization

class Q {
int n;
boolean sse = false;
synchronized int get(){
    while (!sse)
        try{
            wait();
        }catch(InterruptedException e){
            System.out.println("Interrupted Exception Caught");
        }
    System.out.println("Got :" + n);
    sse = false;
    notify();
    return n;
        }
synchronized void put(int n){
    while(sse)
        try{
            wait();
        }catch(InterruptedException e){
         System.out.println("Caught");
        }
    this.n = n;
    sse = true;
    System.out.println("Put :" + n);
    notify();
}

}
class Producer implements Runnable{
    Q q;
    Producer(Q q) {
        this.q = q;
        new Thread(this, "Prodcuer").start();
    }
    public void run(){
        int i = 0;
        while(true) {
        q.put(i++);
        }
    }
}
class Consumer implements Runnable{
    Q q;
    Consumer(Q q) {
        this.q = q;
        new Thread(this, "Consumer").start();
    }
    public void run(){

        while(true) {
        q.get();
        }
    }
}
public class Main {


    public static void main(String[] args) {
  Q q = new Q();
  new Producer(q);
  new Consumer(q);
  System.out.println("Press Control C to stop");
    }

}

我有兩個問題。

Q1。 現在,wait()函數的定義是這樣的:告訴調用線程放棄監視器並進入睡眠狀態,直到其他線程進入同一監視器並調用notify()為止。 現在在該程序中,兩個線程(一個與消費者有關,一個與生產者有關)分別在get和put中使用相同的對象q。 那么,對於任何對象,只要有一個線程使用涉及q的函數,就只存在一個對象q的監視器?

Q2在這里,消費者等待直到生產者通知它,但是生產者也等待直到消費者通知它? 誰先開始? 在輸出中,Producer排在第一位,但是如何?

  1. Q只有一台顯示器
  2. Producer首先啟動,因為您首先在Main中調用了它的構造函數。

關於第二個問題:程序啟動時,Q對象“為空”,這意味着使用者無法獲得任何對象。 因此,消費者必須等到生產者放入東西之后。這意味着生產者將首先打印其“放置”,然后消費者可以檢索它並打印其“獲取”。

另一方面,如果生產者嘗試在消費者將上一個元素從隊列中取出之前再次放一些東西,則生產者必須等待直到被拿走。

這意味着您將獲得交替的“ Put”和“ Get”輸出(假設輸出流不進行某些重新排序)。

這與SynchronousQueue有點不同,在這里生產者可以在隊列之前為空的情況下繼續運行(消費者可以在隊列之前為空的情況下繼續進行),而對於SynchronousQueue,它將等待消費者准備好使用它(這意味着putget 總是在時間上重疊,並且不能在同一線程上調用)。

您的隊列更類似於容量為1的ArrayBlockingQueue。

  1. jvm中的每個對象(實例)都只有一個監視器。 這對於實現預期的行為(即確保一堆線程中只有一個線程繼續執行而其他線程等待)至關重要。

    您可以將鎖可視化為進入房間所需的一種令牌/通行證。 許多醫院采用這種方案來確保只有一名服務員可以陪同特定患者。 如果您想代替當前的服務員,則應該wait()當前的服務員出來並將通行證交給您。 只有這樣,您才能通過安全性進入限制區域。 當然,該方案僅在每個患者只有一次令牌/通行證的情況下有效。 否則,安全人員將不可能知道哪個患者已經有服務員。

  2. 使用您的代碼,生產者線程將首先啟動,因為您要在使用者之前創建生產者。 但是,如果您想知道首先調用get()put()哪一個,則無法保證順序。 實際上,您通常會看到put()首先被調用,因為生產者線程是首先啟動的。 但是從理論上講,仍然有可能首先看到get() 這是可能的,因為線程調度程序可能會在生產者線程到達put()調用之前將其關閉。

暫無
暫無

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

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