简体   繁体   English

使用线程同时访问 Java 同步块?

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

How can two threads access a synchronized block simultaneously?两个线程如何同时访问一个同步块? That is, how can I make one thread give the chance for the other thread to execute a synchronized block, even before this thread finishes the execution of the same synchronized block?也就是说,我怎样才能让一个线程给另一个线程执行同步块的机会,即使在这个线程完成同一个同步块的执行之前?

See wait() , notify() , and notifyAll() .请参阅wait()notify()notifyAll()

Edit: The edit to your question is incorrect.编辑:对您问题的编辑不正确。 The sleep() method does not release the monitor. sleep() 方法不会释放监视器。

For example:例如:

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();
        }
    }
}

It sounds like you might want to consider using more than one synchronized block, particularly if there's a blocking operation that one thread is getting caught on and thus blocking another thread that wants to execute something else in the block.听起来您可能要考虑使用多个同步块,特别是如果有一个线程被捕获的阻塞操作并因此阻塞了另一个想要在块中执行其他内容的线程。

A synchronized block is a block of code which can (by definition) only be accessed by one thread at a time.同步块是(根据定义)一次只能由一个线程访问的代码块。 Saying that you want another thread to enter this block while another thread also currently processes it, does make the synchronized block scheme useless.说您希望另一个线程进入这个块,而另一个线程当前也在处理它,确实使同步块方案无用。

You probably want to split the synchronized block into many other ones.您可能希望将同步块拆分为许多其他块。

A thread can release its monitor using lock.wait() .线程可以使用lock.wait()释放它的监视器。 Another thread can then pick up the monitor and enter the synchronized block.然后另一个线程可以拿起监视器并进入同步块。

Example:例子:

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();
        }
    }
}

This prints:这打印:

Before wait
Before wait
After wait
After wait

However it's not a "hack" to allow a mutually exclusive block to be run non-atomically.然而,允许互斥块以非原子方式运行并不是“黑客”。 If you're going to use very low-level synchronization primitives like this you need to know what you're doing.如果你要使用像这样的非常低级的同步原语,你需要知道你在做什么。

The only way I can see if one thread calls wait() on monitor object.我可以看到一个线程是否在监视器 object 上调用wait()的唯一方法。 Then it will release monitor and wait for notification while other thread can execute synchronized block.然后它会释放监视器并等待通知,而其他线程可以执行同步块。 Then other thread will have to call notify()/notifyAll() so first thread gets monitor back and continue.然后其他线程将不得不调用notify()/notifyAll()以便第一个线程返回监视器并继续。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM