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

发布于 2024-11-25 16:04:25 字数 69 浏览 1 评论 0原文

两个线程如何同时访问同步块?也就是说,如何让一个线程为另一个线程提供执行同步块的机会,甚至在该线程完成同一同步块的执行之前?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

合久必婚 2024-12-02 16:04:25

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

See wait(), notify(), and notifyAll().

Edit: The edit to your question is incorrect. The sleep() method does not release the monitor.

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();
        }
    }
}
娇柔作态 2024-12-02 16:04:25

听起来您可能需要考虑使用多个同步块,特别是如果一个线程正在执行阻塞操作,从而阻塞另一个想要执行块中其他操作的线程。

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.

会发光的星星闪亮亮i 2024-12-02 16:04:25

同步块是(根据定义)一次只能由一个线程访问的代码块。
如果您希望另一个线程进入此块,而另一个线程当前也在处理它,则确实会使同步块方案毫无用处。

您可能想将同步块拆分为许多其他块。

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.

风透绣罗衣 2024-12-02 16:04:25

我可以查看是否有一个线程在监视器对象上调用 wait() 的唯一方法。然后它将释放监视器并等待通知,而其他线程可以执行同步块。然后其他线程必须调用notify()/notifyAll(),以便第一个线程取回监视器并继续。

The only way I can see if one thread calls wait() on monitor object. 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.

雨落□心尘 2024-12-02 16:04:25

线程可以使用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

但是,允许互斥块以非原子方式运行并不是“黑客”。如果您要使用像这样的非常低级的同步原语,您需要知道您在做什么。

A thread can release its monitor using 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文