1

私はアンドロイドでコーディングする方法を学んでいるアナログの男なので、この質問がばかげているように聞こえる場合はご容赦ください。

同期の要点がわかりました。2 つのスレッドがアクセスして変更できるデータがある場合、両方のスレッドのデータ変数の値が矛盾する可能性があります。

メソッドを同期させ、1 つのスレッドが実行を完了する (条件付きチェックを実行する) までメソッドをロックすることは理にかなっていますが、単一のステートメントでそれが問題になるのはなぜでしょうか? 2 つ以上のステートメントの間にスレッド 1 が実行可能な状態から外れる可能性があるため、複数のステートメントで問題になりますが、単一のステートメントのポイントがわかりません。

ここに例があります

ゲームスレッドから呼び出すことができるリスナーがあり、それがデータ変数を変更する場合、なぜこのようにするのでしょうか...

    public void onCompletionListener(MediaPlayer player){
    synchronized (this){
        isPrepared = false;
       }
    }

Music クラスには stop という別のメソッドもあります

   public void stop(){
   mediaPlayer.stop()
    synchronized(this){
    isPrepared = false;
       }
    }

なぜわざわざこれをするのですか?これは、2 つのスレッド間の値の一貫性のために行われますか? もしそうなら、私は揮発性のようなものを使うことができますか? そのほうがいいでしょうか?

同期はお金がかかると聞いたので質問します。より良い代替手段はありますか?

私の質問に答えてくれてありがとう。それは有り難いです。編集:この同期を単一のステートメントで読みましたか?

私は理解していると思います..誰かがそれを詳しく説明できれば素晴らしいでしょう。また、 volatile がより良い代替手段であるかどうかに関する私の最初の質問のパート2には回答がありません:)

4

3 に答える 3

4

これが行われるのは、同期によって、スレッド間のメモリの可視性に関する要件も設定されるためです。

その書き込みが同期化されていないか揮発性でない場合、他のスレッドからいつ見えるようになるかについて、厳格で迅速な要件はありません。別のスレッドが true を示す のコピーをスタックに保持している可能性があり、メイン メモリに戻って、同期または揮発性の参照がない場合に、他のisPrepared誰かが変更されたかどうかを確認することを知らずに永久に実行される可能性があります。isPrepared

volatile キーワードは、他のスレッドが更新を確認できるようにするという差し迫った要件を満たします。クラス/システム全体を見ずに、それが受け入れられる代替品であるかどうかを判断することは不可能です。他の同期メソッドが存在する可能性があり、そのうちの 1 つが実行中に isPrepared の状態を変更することは違法です。揮発性の参照を優先して同期を削除すると、明らかにエラーになります。

于 2013-01-07T01:40:11.577 に答える
0

以前の回答に加えて、場合によっては、単一行のソースコードを複数行のマシン実行可能コードに変換できることを追加したいと思います。

カウンター++

単一の操作のように見えるかもしれませんが、式 counter++ は実際には 3 つの別個の操作です。

1) カウンターの値を読む

2) この値に 1 を加える

3) 更新された値をカウンターに格納する

したがって、この種のステートメントは、マルチスレッド コンテキストでも同期する必要があります。

于 2016-07-12T10:06:52.610 に答える
0

boolean で volatile を使用すると、同期なしでも機能します。
プリミティブ ブール値は 4 バイト値として表され、1 つの (アセンブラー) ステートメントで記述されます。

これは、1 つのスレッドが下位 4 バイトを書き込み、別のスレッドが上位 4 バイトを書き込む可能性がある 8 バイト値 (例: long / double) で動作することが保証されていません。

于 2013-01-07T01:36:05.163 に答える