我是否应该将布尔字段设置为易失性



以下代码是线程安全的吗?我真的需要将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

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

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

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

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

但是假设您有多个线程读取和写入数据库,最好使写入方法/语句同步,并对从数据库中检索的数据使用易失性,以便可以从线程提供多个访问权限来读取数据。

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

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

最新更新