リクエスト インスタンスの FIFO キュー (速度のために事前に割り当てられたリクエスト オブジェクト) を実装し、add メソッドで "synchronized" キーワードを使用することから始めました。メソッドは非常に短いものでした (固定サイズのバッファーに余裕があるかどうかを確認してから、配列に値を追加します)。visualVM を使用すると、スレッドが私が思っていたよりも頻繁にブロックしているように見えました (正確には「モニター」)。そこで、現在のサイズを追跡するなどの目的で AtomicInteger 値を使用するようにコードを変換し、while ループで compareAndSet() を使用します (AtomicInteger は、incrementAndGet() などのメソッドに対して内部的に行うように)。コードはかなり長く見えます。
私が疑問に思っていたのは、同期された短いコードを使用した場合と、同期されたキーワードを使用しない長いコードを使用した場合のパフォーマンスのオーバーヘッドはどうなるかということです (したがって、ロックでブロックすることはありません)。
以下は、synchronized キーワードを使用した古い get メソッドです。
public synchronized Request get()
{
if (head == tail)
{
return null;
}
Request r = requests[head];
head = (head + 1) % requests.length;
return r;
}
以下は、synchronized キーワードを使用しない新しい get メソッドです。
public Request get()
{
while (true)
{
int current = size.get();
if (current <= 0)
{
return null;
}
if (size.compareAndSet(current, current - 1))
{
break;
}
}
while (true)
{
int current = head.get();
int nextHead = (current + 1) % requests.length;
if (head.compareAndSet(current, nextHead))
{
return requests[current];
}
}
}
私の推測では、コードが短くても、ロックでブロックされるリスクがあるため (潜在的にスレッド コンテキスト スイッチなどを引き起こす可能性があります)、synchronized キーワードの方が悪いと思います。
ありがとう!