簡體   English   中英

2個線程如何同時訪問一個同步塊?

[英]How can 2 threads access a synchronized block at the same time?

您能描述一下在多線程環境中以下代碼是如何正常工作的嗎? 我從https://www.javacodegeeks.com/2014/11/multithreading-concurrency-interview-questions-answers.html獲取了代碼。 描述說2個線程可能一個接一個地進入第二個同步塊。 怎么會這樣 有兩個同步塊有什么關系?

public Integer getNextInt() {
    Integer retVal = null;
    synchronized (queue) {
        try {
            while (queue.isEmpty()) {
                queue.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    synchronized (queue) {
        retVal = queue.poll();
        if (retVal == null) {
            System.err.println("retVal is null");
            throw new IllegalStateException();
        }
    }
    return retVal;
}

這很簡單-第一個同步塊(S1)使線程等待,直到隊列變為非空。 第二個同步塊(S2)使單個線程從隊列中獲取一項。

  1. 線程1進入S1。
  2. 線程1存在S1->隊列不為空
  3. 線程2進入S1
  4. 線程2存在S1->隊列仍然不為空
  5. 線程1進入S2->從隊列中取出一個項目,它變為空
  6. 線程1存在S2
  7. 線程2進入S2->嘗試從隊列中獲取元素,但它為空->引發異常。

如您所見,只有1個線程按預期進入了同步塊,但這不能保證正確的同步。

使用同步塊的全部目的是圍繞必須一起執行的代碼段創建“事務”。 沒有機會在“中間”插入另一個線程。

您的示例有兩個街區; 並且很可能第一個線程離開了第一個塊; 但是第二個線程進入,第一個線程可以進入第二個塊。

這就是全部。

queue.wait()釋放鎖定,該鎖定將應用於同步塊。 換句話說,當queue.wait()時,其他線程可以自由進入同步塊。 下面,我提供了一個工作示例,其中5個線程同時輸入相同的同步塊。 您可以檢查以下代碼,以了解wait ()和notiy()/ notifyAll()方法如何工作:

public class Main {
    static Object lock = new Object();
    public static void main(String args[]) throws InterruptedException {

        Runnable r = () -> {
            System.out.println(" ThreadID: " + Thread.currentThread().getId() + " has started");
            synchronizedBlockExecution();
        };

        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(r);
            t.start();
        }

        Thread.sleep(1000);
        System.out.println("------all threads are notifed to stop waiting!---------");
        synchronized (lock) {
            lock.notifyAll();
        }

    }

    public static void synchronizedBlockExecution() {
            System.out.println("Thread: " + Thread.currentThread().getId() + " is entering synchronized block");
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("Thread: " + Thread.currentThread().getId() + " has left synchronized block");
    }
}

T1進入S1
T1存在S1
T2等待T1從S1完成
T1完成並進入S2
S1對於T2是免費的
T2進入S1
這樣,T1和T2可以同時處於兩個不同的同步塊中。 這將提高性能。 程序員應該編寫同步塊而不是方法,因為它允許兩個線程同時在兩個單獨的塊中工作。

暫無
暫無

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

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