以下代码是线程安全的吗?我真的需要将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,但这并不意味着您提供的代码片段本身是线程安全的。因此,数据就绪应标记为易失性。
如您所知,易失性意味着主内存中只有一个变量副本,而不是由线程缓存的副本。我认为在这种情况下这是最合适的。