2

以下代码是线程安全的吗?我真的需要设置dataReadyvolatile,尽管一个线程只有一次写入和多次读取(如下所示的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
4

3 回答 3

2

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

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

于 2012-07-05T08:06:41.777 回答
1
though there is only one write and multiple reads from one thread 

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

但是假设你有多个线程读取和写入数据库,最好将写入方法/语句设置为同步,并在从数据库中检索的数据上使用 volatile,这样可以从线程中获得多个访问权限来读取数据.

于 2012-07-05T02:45:03.373 回答
0

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

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

于 2012-07-05T02:50:40.660 回答