在Java中,synchronized()/ wait()/ notifyAll()做了什么?

时间:2011-08-02 15:40:54

标签: java android multithreading thread-safety

  

可能重复:
  Java Synchronization

我正在阅读开始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();
        }

7 个答案:

答案 0 :(得分:49)

synchronized关键字用于保持变量或方法的线程安全。如果将变量包装在同步块中,如下所示:

synchronized(myVar) {
    // Logic involing myVar
}

然后,当synchronized块中的逻辑正在运行时,任何尝试从另一个线程修改myVar的值将等到块完成执行。它确保进入块的值在该块的生命周期内是相同的。

答案 1 :(得分:31)

This Java Tutorial可能会帮助您了解对象上使用synchronized的内容。

当调用object.wait()时,它将释放该对象上的锁定(当您说synchronized(object)时会发生这种情况),并冻结该线程。然后线程等待,直到由单独的线程调用object.notify()object.notifyAll()。一旦发生其中一个调用,它将允许因object.wait()而停止的任何线程继续。这样做意味着调用object.notify()object.notifyAll()的线程将冻结并将控制传递给等待线程,这只是意味着这些等待线程现在能够继续,而在它们没有之前。

答案 2 :(得分:10)

当像这样使用时:

private synchronized void someMehtod()

你得到这些效果:

  

1。首先,对同一对象的两个同步方法的调用不可能进行交错。当一个线程正在为对象执行同步方法时,所有其他线程都会调用同一对象的同步方法阻塞(暂停执行),直到第一个线程完成对象为止。

     

2. 其次,当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立先发生关系。这可以保证对所有线程都可以看到对象状态的更改。

(取自here

使用同步代码块时会产生类似的效果:

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

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

  // more actions...
}

正如here

所解释的那样

答案 3 :(得分:4)

Java(Android所基于的)可以在多个线程下运行,这些线程可以使用多个cpu核心。多线程意味着您可以让Java在同一时刻执行两个进程。如果您有一块代码或方法需要确保一次只能由一个线程操作,则可以同步该代码块。

Here is the official Java explanation from Oracle

重要的是要知道使用synchronized会涉及处理器/ io成本,而您只想在需要时使用它。研究哪些Java类/方法是线程安全的也很重要。例如,++ increment运算符不保证是线程安全的,而您可以轻松创建一个同步代码块,使用+ = 1递增值。

答案 4 :(得分:1)

只有一个线程可以处于活动状态,并且内部块由给定对象同步。 调用等待停止放弃此权限并停用当前线程,直到有人调用notify(all)() 然后,非活动线程开始想要再次在synchronized块中运行,但是与所有其他需要它的线程一样处理。只有一个人选择(程序员不能影响也不依赖于哪一个)才能实现。

答案 5 :(得分:1)

java中的同步关键字用于两件事。

第一个含义是所谓的临界区,即可以由一个线程同时访问的代码的一部分。传递给synchronized的对象允许某种命名:如果在synchronized(a)中运行一个代码,则它无法访问synchronized(a)中的其他块,但可以访问{{1}的代码块}}

其他问题是线程间通信。线程可以等到其他线程通知它。 wait和notify都必须写入synchronized(b)块。

这是一个非常简短的描述。我建议你搜索一些关于多线程的教程并阅读它。

答案 6 :(得分:0)

关键字synchronized与wait和notify操作一起形成nonblocking condition monitor,这是一个用于协调多个线程的构造。