我应该将布尔字段设置为volatile吗?

时间:2012-07-05 02:34:30

标签: java android multithreading concurrency volatile

以下代码是否是线程安全的?我是否真的需要将dataReady设置为volatile,尽管一个线程只有一次写入和多次读取(如下所示,while循环)?

public class MyApplication extends Application
{
    /* a flag indicates if the data is fully retrieved from the database */
    private volatile boolean dataReady = false;

    @Override
    public void onCreate()
    {
        super.onCreate();

        new AsyncTask<Void, Void, Void>()
        {
            @Override
            protected Void doInBackground(Void... params)
            {
                // retrieve data from the database
                return null;
            }

            @Override
            protected void onPostExecute(Void result)
            {
                dataReady = true;
            }
        }.execute();
    }

    public boolean isDataReady()
    {
        return dataReady;
    }
}

在其他线程(不是主线程)上:

while(!getApplication().isDataReady()); // wait until the data is ready

3 个答案:

答案 0 :(得分:2)

将布尔值标记为volatile可保证可见性,换句话说,它可确保所有线程都能看到其当前值。由于您在不同的线程中进行写入和读取,因此必须将布尔值标记为volatile

如果你没有将它标记为volatile,那么你的主线程将dataReady设置为true并且另一个线程将该标志视为false并且很可能(但不是系统的)继续循环。在更糟糕的情况下,它甚至可能成为无限循环。

答案 1 :(得分:1)

though there is only one write and multiple reads from one thread 

当你提到的单线程时,你正在写一次并多次读取,那么我不认为volatile是需要的,因为volatile反映了一个线程对数据所做的更改另一个,

但假设你有多线程读写数据库,最好将写入方法/语句设为同步对数据使用volatile ,从数据库中检索,因此可以从线程进行多次访问以读取数据。

答案 2 :(得分:0)

代码不一定是线程安全的。虽然我知道可以设计系统以确保只有一个线程创建MyApplication的实例,然后调用onCreate,这并不意味着您提供的代码片段本身就是线程安全的。因此,dataReady应标记为volatile。

如您所知,volatile意味着主内存中只有一个变量副本,而不是由线程缓存的副本。我认为在这种情况下这是最合适的。