2

次のコードはスレッドセーフですか? 1 つのスレッドから 1 つの書き込みと複数の読み取りしかない (以下に示すように while ループを使用) にもかかわらず、実際dataReadyに beに設定する必要がありますか?volatile

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

としてマークしない場合、メイン スレッドがtrue に設定され、他のスレッドがフラグを false と見なしてループを続行するvolatile可能性が非常に高くなります (体系的ではありません) 。dataReady最悪の場合、無限ループに陥る可能性さえあります。

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

あなたが言及したように、その単一のスレッドが1回書き込み、複数回読み取っている場合、揮発性はあるスレッドによってデータに対して行われた変更を別のスレッドに反映するため、揮発性は必要ないと思います。

ただし、データベースの読み取りと書き込みを行う複数のスレッドがあるとします。書き込みメソッド/ステートメントを synchronized として作成し、データベースから取得したデータに対して volatileを使用することをお勧めします。これにより、スレッドからの複数のアクセスでデータを読み取ることができます。 .

于 2012-07-05T02:45:03.373 に答える
0

コードは必ずしもスレッドセーフではありません。1 つのスレッドのみが MyApplication のインスタンスを作成してから onCreate を呼び出すようにシステムが設計されている可能性があることは理解していますが、それは提供したコード スニペット自体がスレッドセーフであることを意味するものではありません。したがって、dataReady は揮発性としてマークする必要があります。

ご存じのように、volatile とは、変数のコピーがスレッドによってキャッシュされるのではなく、メイン メモリに変数のコピーが 1 つだけ存在することを意味します。この場合はこれが最も適切だと思います。

于 2012-07-05T02:50:40.660 に答える