Одновременный доступ к синхронизированному блоку Java с использованием потоков? - PullRequest
2 голосов
/ 22 июля 2011

Как два потока могут одновременно обращаться к синхронизированному блоку?То есть, как я могу заставить один поток дать возможность другому потоку выполнить синхронизированный блок даже до того, как этот поток завершит выполнение того же синхронизированного блока?

Ответы [ 5 ]

5 голосов
/ 22 июля 2011

См. wait () , notify () и notifyAll () .

Редактировать: Theизменить на свой вопрос неверно.Метод 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();
        }
    }
}
1 голос
/ 22 июля 2011

Единственный способ узнать, вызывает ли один поток wait() для объекта монитора. Затем он отключит монитор и будет ожидать уведомления, пока другой поток сможет выполнить синхронизированный блок. Тогда другой поток должен будет вызвать notify()/notifyAll(), чтобы первый поток вернул монитор и продолжил.

1 голос
/ 22 июля 2011

Поток может освободить свой монитор, используя 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

Однако это не «взлом», чтобы позволить взаимоисключающему блоку быть запущенным неатомно. Если вы собираетесь использовать подобные низкоуровневые примитивы синхронизации, вам нужно знать, что вы делаете.

1 голос
/ 22 июля 2011

Синхронизированный блок - это блок кода, к которому (по определению) может обращаться только один поток за раз.Сказав, что вы хотите, чтобы другой поток вошел в этот блок, в то время как другой поток также в настоящее время обрабатывает его, делает схему синхронизированных блоков бесполезной.

Возможно, вы хотите разделить синхронизированный блок на множество других.

1 голос
/ 22 июля 2011

Звучит так, как будто вы захотите рассмотреть возможность использования более одного синхронизированного блока, особенно если есть блокирующая операция, в которую попадает один поток, и, таким образом, блокирующая другой поток, который хочет выполнить что-то еще в блоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...