Синхронизирован нужен тут - PullRequest
0 голосов
/ 03 декабря 2009

У меня есть Java-апплет. Класс внутри этого апплета создает поток для выполнения некоторой работы, ожидая 30 секунд для завершения этой работы, если он не завершен в течение 30 секунд, он устанавливает логическое значение для остановки потока. Ожидание и логическое изменение находятся в синхронизированном блоке. Это необходимо, учитывая, что кроме этих двух потоков не выполняется никакой другой поток.

    System.out.println("Begin Start Session");
    _sessionThread = new SessionThread();
    _sessionThread.start();

    synchronized (_sessionThread)
    {
        _sessionThread.wait(30000);
        _sessionThread._stopStartSession = true;
    }

Почему я не мог просто сделать это вместо этого?

    System.out.println("Begin Start Session");
    _sessionThread = new SessionThread();
    _sessionThread.start();

    _sessionThread.wait(30000);
    _sessionThread._stopStartSession = true;

Метод запуска SessionThread. Вызывает метод JNI для вызова библиотеки DLL, чтобы открыть окно программы.

public void run()
{
    try
    {
        startExtraSession();
    } 
    catch (Throwable t)
    {
        t.printStackTrace();
    }
        notify();
}


private native void openSessionWindow(String session_file);

private void startExtraSession()
{
    final String method_name = "startExtraSession";

    String title = _sessionInfo._title;
    long hwnd = 0;

    openSessionWindow(_sessionInfo._configFile);

    try
    {
        //Look for a window with the predefined title name...
        while ((hwnd = nativeFindWindow(title)) == 0 && !_stopStartSession)
        {
            Thread.sleep(500);
    }
    }
    catch(Throwable t)
    {
       t.printStackTrace();
    }
}

1. Нужна ли синхронизация?
2. Есть ли лучший способ сделать это, кроме использования потоков?

Ответы [ 4 ]

3 голосов
/ 03 декабря 2009

Для того чтобы иметь возможность вызывать wait(long) для данного потока, требуется, чтобы у него была блокировка на объекте. Это достигается с помощью синхронизированного блока на указанном объекте.

См. Спецификация J2SE по использованию wait.

Получение блокировки / монитора в Java может быть сделано различными способами:

  • В synchronized (нестатическом) методе поток владеет монитором объекта, на который ссылается this.
  • В методе static synchronized потоку принадлежит монитор по дескриптору Class<?> для класса, который определяет указанный метод.
  • В блоке synchronized(x) поток имеет монитор на x.

Этот замок будет снят, если:

  • Вы выходите за пределы блока синхронизированного кода (будь то метод, статический метод или явный блок).
  • Вы вызвали wait() или один из его вариантов (и вы повторно получите его непосредственно перед возвратом метода).

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

1 голос
/ 04 декабря 2009

Существует очень простая причина, по которой вам нужно synchronized, чтобы позвонить wait

synchronized гарантирует, что никто не звонит notify или notifyAll в то время, когда вы звоните wait

Например: Тема 1

synchronized( obj )
{
    triggerActionOnThread2();
    obj.wait();
}

Поток 2 (запускается triggerActionOnThread2)

    ...
    synchronized( obj )
    {
        obj.notify();
    }

Если у вас нет синхронизированных блоков, то notify может произойти до (или во время) wait, а затем wait пропустит notify, и вы можете повесить поток 1.

Представьте вышеперечисленные блоки кода без блоков synchronized и представьте, что поток 2 выполняется через весь путь уведомления до вызова wait.

Кстати, я задаю этот вопрос на собеседованиях с инженерами Java, когда работа будет включать многопоточное программирование.

0 голосов
/ 05 декабря 2009

Если логическое значение является единственным общим состоянием между потоками, объявление логического переходного процесса гарантирует, что изменения в нем будут видны между потоками, как если бы блок синхронизации вокруг доступа к логическому.

0 голосов
/ 03 декабря 2009

Можете ли вы опубликовать код SessionThread? Вы не можете ждать, если у вас нет блокировки, поэтому вам нужно синхронизироваться (_sessionThread) для выполнения _sessionThread.wait (30000); Не уверен, что с _sessionThread._stopStartSession = true;

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