Подтвердить что ты не робот

Что делает synchronized()/wait()/notifyAll() в Java?

Возможный дубликат:
Синхронизация Java

Я читаю книгу "Начало игр для Android".

Он много использует synchronized(), но я действительно не понимаю, что он делает. Я не использовал Java в течение длительного времени, и я не уверен, что когда-либо использовал многопоточность.

В примерах Canvas используется synchronized(this). Однако в примере OpenGL ES он создает объект с именем stateChanged, а затем использует synchronized(stateChanged). Когда изменяется состояние игры, он вызывает stateChanged.wait(), а затем stateChanged.notifyAll();

Некоторые коды:

    Object stateChanged = new Object();

    //The onPause() looks like this:
    public void onPause()
        {
            synchronized(stateChanged)
            {
                if(isFinishing())
                    state = GLGameState.Finished;
                else
                    state = GLGameState.Paused;

                while(true)
                {
                    try
                    {
                        stateChanged.wait();
                        break;
                    } catch(InterruptedException e)
                    {
                    }
                }
            }
        }
//The onDrawSurface looks like this:
public void onDrawFrame(GL10 gl)
    {
        GLGameState state = null;
        synchronized(stateChanged)
        {
            state = this.state;
        }

        if(state == GLGameState.Running)
        {

        }

        if(state == GLGameState.Paused)
        {
            synchronized(stateChanged)
            {
                this.state = GLGameState.Idle;
                stateChanged.notifyAll();
            }
        }

        if(state == GLGameState.Finished)
        {
            synchronized(stateChanged)
            {
                this.state = GLGameState.Idle;
                stateChanged.notifyAll();
            }
        }
    }

//the onResume() looks like this:
synchronized(stateChanged)
        {
            state = GLGameState.Running;
            startTime = System.nanoTime();
        }
4b9b3361

Ответ 1

Этот учебник по Java, вероятно, поможет вам понять, что использует синхронизированный объект.

Когда вызывается object.wait(), он освободит блокировку, удерживаемую на этом объекте (что происходит, когда вы говорите synchronized(object)), и заморозите поток. Затем поток ожидает до тех пор, пока object.notify() или object.notifyAll() не будет вызван отдельным потоком. После того, как произойдет один из этих вызовов, он позволит остановить все потоки, которые были остановлены из-за object.wait(). Это означает, что не означает, что поток, который вызвал object.notify() или object.notifyAll(), замерзнет и передаст управление ожидающему потоку, это просто означает, что эти ожидающие потоки теперь могут продолжать, тогда как раньше они не были.

Ответ 2

Ключевое слово synchronized используется для сохранения потоков или методов в потоковом режиме. Если вы переносите переменную в синхронизированный блок следующим образом:

synchronized(myVar) {
    // Logic involing myVar
}

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

Ответ 3

При использовании следующим образом:

private synchronized void someMehtod()

Вы получаете следующие эффекты:

1. Во-первых, невозможно, чтобы две вызовы синхронизированных методов на одном объекте чередовали. Когда один поток выполняет синхронизированный метод для объекта, все другие потоки, которые вызывают синхронизированные методы для одного и того же объекта (приостанавливать выполнение) до тех пор, пока первый поток не будет выполнен с объектом.

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

(Взято из здесь)

Вы получаете аналогичный эффект при использовании синхронизированного блока кода:

private void someMethod() {
  // some actions...

  synchronized(this) {
    // code here has synchronized access
  }

  // more actions...
}

Как объясняется здесь

Ответ 4

Java (на базе которой работает Android) может работать под несколькими потоками, которые могут использовать несколько ядер процессора. Многопоточность означает, что вы можете заставить Java выполнять два процесса в один и тот же момент. Если у вас есть блок кода или метод, который вам нужно обеспечить, он может управляться только одним потоком за раз, вы синхронизируете этот блок кода.

Вот официальное объяснение Java от Oracle

Важно знать, что затраты на процессор /io связаны с использованием синхронизации, и вы хотите использовать его только тогда, когда вам это нужно. Также важно исследовать, какие классы/методы Java являются потокобезопасными. Например, оператор приращения ++ не является защищенным потоком, тогда как вы можете легко создать блок синхронизированного кода, который увеличивает значение с помощью + = 1.

Ответ 5

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

Ответ 6

Синхронизированное ключевое слово в java используется для 2-х вещей.

Первое значение - это так называемый критический раздел, т.е. часть кода, к которой может одновременно обращаться один поток. Объект, который вы передаете в synchronized, допускает какое-то именование: если один код запущен в synchronized(a), он не может получить доступ к другому блоку, который находится в synchronized(a), но может получить доступ к блоку кода в synchronized(b).

Другой проблемой является межпоточная связь. Тема может ждать, пока другой поток не уведомит об этом. Оба ожидания и уведомления должны быть записаны в блок synchronized.

Это было очень короткое описание. Я бы предложил вам найти учебник по многопоточности и прочитать его.

Ответ 7

Синхронизированное ключевое слово вместе с операциями wait и notify формирует монитор неблокирующего состояния, конструкцию, полезную для координации нескольких потоков.