はじめに
- Java言語でvolatileによって変更された変数は、スレッドシナリオでの可視性を保証できます。
- プロセッサ命令並べ替え防ぐため、視認性に問題があるだろう、マルチスレッド環境で命令再配置を
つまり、揮発性変数xにアクセスできるスレッドABがあります。
スレッドAがxを変更すると、スレッドBは変数xに再度アクセスして、xの最新の値を取得できます。
不揮発性変数はこれを保証できません。
可視性の原則
揮発性変数修飾子が適切に使用されている場合、スレッドコンテキストの切り替えとスケジューリングが発生しないため、同期よりも使用および実行の方が安価です。
volatile変数で装飾された共有変数が書き込まれると、ロックアセンブリコードが使用されます。ロックプレフィックス付きの命令は、マルチコアプロセッサで2つのことを引き起こします。
- 現在のプロセッサキャッシュラインのデータがシステムメモリに書き戻されます。
- このメモリへの書き戻し操作により、他のCPUのメモリアドレスにキャッシュされたデータが無効になります。(他のCPUはキャッシュスニッフィングによってキャッシュを無効にします)
再配置を防止する原理
- 各揮発性書き込み操作の前にStoreStoreバリアを挿入し、書き込み操作の後にStoreLoadバリアを挿入します
- 各揮発性読み取り操作の前にLoadLoadバリアを挿入し、読み取り操作の後にLoadStoreバリアを挿入します。
Javaメモリバリア
- Javaのメモリバリアは通常4つのタイプと呼ばれます。つまり、LoadLoad、StoreStore、LoadStoreです。StoreLoadは実際には上記の2つの組み合わせであり、一連のバリアとデータ同期機能を備えています。
- LoadLoadバリア:このようなステートメントLoad1; LoadLoad; Load2の場合、Load2によって読み取られるデータと後続の読み取り操作にアクセスする前に、Load1によって読み取られるデータが読み取られていることを確認してください。
- StoreStoreバリア:このようなステートメントStore1; StoreStore; Store2の場合、Store2以降の書き込み操作が実行される前に、Store1の書き込み操作が他のプロセッサーから見えることを確認してください。
- LoadStoreバリア:このようなステートメントLoad1; LoadStore; Store2の場合、Store2および後続の書き込み操作がフラッシュされる前に、Load1によって読み取られるデータが読み取られることを確認してください。
- StoreLoadバリア:このようなステートメントStore1; StoreLoad; Load2の場合、Load2および後続のすべての読み取り操作が実行される前に、Store1の書き込みがすべてのプロセッサから見えるようにします。そのオーバーヘッドは4つの障壁の中で最大のものです。ほとんどのプロセッサ実装では、このバリアは全能バリアであり、他の3つのメモリバリアの機能を組み合わせています
見積もり
https://www.jianshu.com/p/2ab5e3d7e510
https://www.cnblogs.com/chenssy/p/6379280.html