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

时间:2011-07-21 21:10:29

标签: java multithreading block execution simultaneous

两个线程如何同时访问同步块?也就是说,即使在此线程完成相同同步块的执行之前,如何让一个线程为其他线程提供执行同步块的机会呢?

5 个答案:

答案 0 :(得分:5)

请参阅wait()notify()notifyAll()

修改:您的问题的修改不正确。 sleep() method 释放显示器。

例如:

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

同步块是一个代码块,可以(根据定义)一次只能由一个线程访问。 假设您希望另一个线程进入此块,而另一个线程当前也处理它,确实使同步块方案无效。

您可能希望将已同步的块拆分为许多其他块。

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

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