簡體   English   中英

使用線程同時訪問 Java 同步塊?

[英]Simultaneous access to a Java synchronized block using threads?

兩個線程如何同時訪問一個同步塊? 也就是說,我怎樣才能讓一個線程給另一個線程執行同步塊的機會,即使在這個線程完成同一個同步塊的執行之前?

請參閱wait()notify()notifyAll()

編輯:對您問題的編輯不正確。 sleep() 方法不會釋放監視器。

例如:

private static final Object lock = new Object();

public static void main(String[] args) {
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    executorService.execute(new One());
    executorService.execute(new Two());
}

static class One implements Runnable {
    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("(One) I own the lock");
            System.out.println("(One) Giving up the lock and waiting");
            try {
                lock.wait();
            } catch (InterruptedException e) {
                System.err.println("(One) I shouldn't have been interrupted");
            }
            System.out.println("(One) I have the lock back now");
        }
    }
}

static class Two implements Runnable {
    @Override
    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            System.err.println("(Two) I shouldn't have been interrupted");
        }
        synchronized (lock) {
            System.out.println("(Two) Now I own the lock (Two)");
            System.out.println("(Two) Giving up the lock using notify()");
            lock.notify();
        }
    }
}

聽起來您可能要考慮使用多個同步塊,特別是如果有一個線程被捕獲的阻塞操作並因此阻塞了另一個想要在塊中執行其他內容的線程。

同步塊是(根據定義)一次只能由一個線程訪問的代碼塊。 說您希望另一個線程進入這個塊,而另一個線程當前也在處理它,確實使同步塊方案無用。

您可能希望將同步塊拆分為許多其他塊。

線程可以使用lock.wait()釋放它的監視器。 然后另一個線程可以拿起監視器並進入同步塊。

例子:

public class MultipleThreadsInSynchronizedBlock {
    public static void main(String... args) {
        final Object lock = new Object();
        Runnable runnable = new Runnable() {
            public void run() {
                synchronized (lock) {
                    System.out.println("Before wait");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                    }
                    System.out.println("After wait");
                }
            }
        };
        new Thread(runnable).start();
        new Thread(runnable).start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }

        synchronized (lock) {
            lock.notifyAll();
        }
    }
}

這打印:

Before wait
Before wait
After wait
After wait

然而,允許互斥塊以非原子方式運行並不是“黑客”。 如果你要使用像這樣的非常低級的同步原語,你需要知道你在做什么。

我可以看到一個線程是否在監視器 object 上調用wait()的唯一方法。 然后它會釋放監視器並等待通知,而其他線程可以執行同步塊。 然后其他線程將不得不調用notify()/notifyAll()以便第一個線程返回監視器並繼續。

暫無
暫無

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

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