インターネットの激しい開発により、ユーザーのボリュームの拡大によって引き起こされる同時セキュリティの問題にますます多くのインターネット企業が直面しています。この記事では、Javaの並行性におけるいくつかの一般的なロックメカニズムに焦点を当てています。
1。ポジティブロック
バイアスロックは、JDK1.6によって提案されているロック最適化メカニズムです。コアのアイデアは、プログラムが競合しない場合、以前に入手したスレッド同期操作がキャンセルされるということです。つまり、ロックがスレッドによって取得された場合、バイアスモードに入ります。スレッドが再度ロックを要求する場合、関連する同期操作を実行する必要はなく、操作時間を節約できます。他のスレッドがロックリクエストを作成すると、ロックはバイアスモードを終了します。 -xx:+useBiasedLockingをJVMで使用します
パッケージjvmproject; import java.util.list; import java.util.vector; public class biased {public static list <integer> numberlist = new vector <integer>(); public static void main(string [] args){long begin = system.currenttimemillis(); int count = 0; int startnum = 0; while(count <10000000){numberlist.add(startnum); startnum+= 2; count ++; } long end = system.currenttimemillis(); system.out.println(end-begin); }}ベクトルを初期化し、100,000,000個の整数オブジェクトを追加してから、時間差を出力します。これは、バイアスロックの性能をテストするために使用されます。アレイリストの代わりにベクトルを使用する必要がある理由については?
ArrayListはスレッドインセンスであるため、Vectorはスレッドセーフです。これは十分に具体的ではないかもしれません。ソースコードを見ることができます。
ベクターのほとんどすべての操作は相乗化されていますが、アレイリストはそうではないため、ベクトルはスレッドセーフです。
次に、バイアスロックの開口部がプログラムのパフォーマンスに偏っていないロックの開口部がどれだけ影響を与えるかをテストしましょう。
JVMスタートアップ(バイアスロックをオンにする)パラメーターを次のように構成します。
JVMスタートアップ(クローズバイアスロック)パラメーターを次のように構成します。
完璧!バイアスロックを有効にするプログラムの実行時間は大幅に短くなっています。バイアスロックを有効にしないよりも、偏ったロックを有効にすることは、特定の利点があります。単一のスレッドでオブジェクトを操作する同期方法。実際、このように理解することもできます。同期メソッドを使用してベクトルオブジェクトを操作するスレッドが1つしかない場合、ベクトルの動作はアレイリストの操作に変換されます。
バイアスロックは、ロックが競争力がある場合、強力な最適化効果を持ちません。なぜなら、大量の競合により、スレッドがロックを保持することで継続的に切り替えられるため、ロックがバイアスモードのままでいることは困難です。現時点では、バイアスロックを使用すると、パフォーマンスの最適化が得られないだけでなく、システムのパフォーマンスが低下する可能性があります。したがって、激しい競争の場合、あなたはそれを使用しようとすることができます。
-xx: - usebiastedlockingパラメーターは、バイアスロックを無効にします。
2。軽量ロック
バイアスロックが故障した場合、Java仮想マシンはスレッドに軽量ロックを適用するように依頼します。軽量ロックは仮想マシン内に実装され、BasicObjectLockになるオブジェクトを使用して実装されます。これは、BasicLockオブジェクトとロックを保持しているJavaオブジェクトポインターで構成されています。 BasicObjectLockオブジェクトはJavaスタックフレームに配置されています。 Display_Headerフィールドは、BasicLockオブジェクト内にも維持されます。これは、オブジェクトのヘッダーのマークワードをバックアップするために使用されます。
スレッドがオブジェクトのロックを保持すると、オブジェクトのヘッダーマークワード情報は次のとおりです
[Ptr | 00]ロックされています
最後の2つのビットは00であり、マークワード全体はBasicLockオブジェクトへのポインターです。 BasicObjectLockオブジェクトはスレッドスタックにあるため、ポインターはロックを保持するスレッドスタックスペースを指す必要があります。スレッドがオブジェクトを保持するかどうかを判断する必要がある場合、オブジェクトヘッダーのポインターが現在のスレッドのスタックアドレス範囲内にあるかどうかを単純に判断する必要があります。同時に、BasicLockオブジェクトの表示_headerは、元のオブジェクトのマークワードコンテンツをバックアップし、BasicObjectLockオブジェクトのOBJフィールドはロックを保持しているオブジェクトのヘッドを指します。
3。ヘビー級ロック
軽量ロックが失敗すると、仮想マシンはヘビー級ロックを使用します。ヘビー級ロックを使用する場合、オブジェクトのマークワードは次のとおりです。
[Ptr | 10]モニター
操作中、スレッドはオペレーティングシステムレベルで吊り下げられる場合があります。その場合、スレッド間の切り替えと呼び出しのコストが大幅に増加します。
4。スピンロック
スピンロックは、ロックが取得されていないときにスレッドを吊り下げないようにすることができますが、代わりに空のループの実行に切り替えます(つまり、いわゆるスピン、つまり空のループ自体を実行することを意味します)。いくつかの空のループの後にスレッドがロックを取得できる場合、それは引き続き実行されます。スレッドがまだロックを取得できない場合、吊り下げられます。
スピンロックを使用した後、スレッドが中断される可能性は比較的減少し、スレッド実行の一貫性は比較的強化されます。したがって、ロックとあまり競争しておらず、非常に短い時間を過ごしている同時のスレッドに対して特定の肯定的な重要性を持っています。ただし、ロックやシングルスレッドロックと激しく競争力のある同時プログラムが長い間占有されているため、スピンロックは、スピン待機後に対応するロックを断固として取得できません。これはCPU時間を浪費するだけでなく、必然的に最終的に停止された動作を備えているだけでなく、システムリソースを無駄にします。
JDK1.6では、Java仮想マシンは、スピンロックを有効にするために-xx:+Usespinningパラメーターを提供し、-xx:preblockspinパラメーターを使用して、スピンロックが待機する回数を設定します。
JDK 1.7から、スピンロックのパラメーターがキャンセルされます。仮想マシンは、ユーザーが構成したスピンロックをサポートしなくなりました。スピンロックは常に実行され、スピンロックの数は仮想マシンによって自動的に調整されます。