この記事では、同期ロックから Java8 の新しい StampedLock までの比較分析を行っています。Java8 の新機能、StampedLock に興味のある方はぜひ一緒にご覧ください。Java8 は小さな API の改善です。同期などの記事は、マルチスレッド同時プログラミング
プログラミングでは常に古いトピックであり、これは最悪の場合、アプリケーションのスループットやその他のパフォーマンス指標を低下させることになると思います。 、ハングしてクラッシュしますが、この場合でも、情報の正確性を確保する必要があるため、選択の余地はありません。したがって、この記事では、同期ロックから Java 8 の新しい StampedLock までの比較分析を行うことにしました。StampedLock は誰もが失望するものではないと信じています。
synchronizedjava5 より前では、同期は主に synchronized を使用して実現されていました。これは Java 言語のキーワードであり、メソッドまたはコード ブロックを変更するために使用すると、最大 1 つのスレッドがコードを同時に実行することが保証されます。
4 つの異なる同期ブロックがあります:1. インスタンス メソッド
2. 静的メソッドの同期ブロック
4. 皆さんはこれを知っているはずです。馴染みのないものなので、詳細は説明しません
synchronized(this) // do operation }概要: Synchronized は、マルチスレッド同時プログラミングにおいて常にベテランの役割を果たしています。 , ただし、Java SE1.6ではSynchronizedにさまざまな最適化が行われた後、パフォーマンスも向上しました。
これは、Java 5 によって java.util.concurrent.locks に追加された新しい API です。 Lock はインターフェイスです。コア メソッドは、lock()、unlock()、および tryLock() です。実装クラスには、ReentrantLock、ReentrantReadWriteLock.ReadLock、ReentrantReadWriteLock.WriteLock が含まれます。同じメモリセマンティクス。
同期とは異なり、Lock は完全に Java で書かれており、Java レベルでの JVM 実装とは何の関係もありません。 Lock は、より柔軟なロック メカニズムを提供します。また、ロック投票、時限ロック待機、割り込みロック待機など、同期では提供されない多くの機能が提供されますが、ロックはコードを通じて実装されるため、ロックが確実に解放されるように、unLock()最後に{}以下は Lock のコード例です
rwlock.writeLock().lock(); try { // do operation } finally { rwlock.writeLock().unlock(); }
概要: 同期よりも柔軟でスケーラブルなロック メカニズムですが、とにかく、同期コードの方が記述が簡単です
StampedLock
ReentrantReadWriteLock は、読み取り/書き込みロックがない場合にのみ書き込みロックを取得できます。これは、悲観的な読み取り (Pessimistic Reading) を実装するために使用できます。つまり、実行が読み取りの場合、書き込み先の別の実行が存在する可能性があります。同期を維持するには、ReentrantReadWriteLock の読み取りロックが便利です。 ただし、読み取りが多く書き込みが少ない場合、ReentrantReadWriteLock を使用すると、書き込みスレッドが飢餓の問題に遭遇する可能性があります。つまり、書き込みスレッドがロックを獲得するために競合できず、常に待機状態になります。
StampedLock 制御ロックには 3 つのモード (書き込み、読み取り、オプティミスティック読み取り) があります。StampedLock の状態は、バージョンとモードの 2 つの部分で構成され、対応するアクセスを表すチケット スタンプとして数値を返します。ロック状態。数値 0 は、書き込みロックがアクセスを許可されていないことを示します。読み取りロックは、悲観的ロックと楽観的ロックに分類されます。例外をスローする
)。この小さな改善が大きな違いを生む可能性があります。プログラムのスループットを向上させます。 !
以下は Java doc によって提供される StampedLock の例です
class Point { private double x, y; private final StampedLock sl = new StampedLock(); void move(double deltaX, double deltaY) { // an exclusively locked method long stamp = sl.writeLock(); try { x += deltaX; y += deltaY; } finally { sl.unlockWrite(stamp); } } //下面看看乐观读锁案例 double distanceFromOrigin() { // A read-only method long stamp = sl.tryOptimisticRead(); //获得一个乐观读锁 double currentX = x, currentY = y; //将两个字段读入本地局部变量 if (!sl.validate(stamp)) { //检查发出乐观读锁后同时是否有其他写锁发生? stamp = sl.readLock(); //如果没有,我们再次获得一个读悲观锁 try { currentX = x; // 将两个字段读入本地局部变量 currentY = y; // 将两个字段读入本地局部变量 } finally { sl.unlockRead(stamp); } } return Math.sqrt(currentX * currentX + currentY * currentY); } //下面是悲观读锁案例 void moveIfAtOrigin(double newX, double newY) { // upgrade // Could instead start with optimistic, not read mode long stamp = sl.readLock(); try { while (x == 0.0 && y == 0.0) { //循环,检查当前状态是否符合 long ws = sl.tryConvertToWriteLock(stamp); //将读锁转为写锁 if (ws != 0L) { //这是确认转为写锁是否成功 stamp = ws; //如果成功 替换票据 x = newX; //进行状态改变 y = newY; //进行状态改变 break; } else { //如果不能成功转换为写锁 sl.unlockRead(stamp); //我们显式释放读锁 stamp = sl.writeLock(); //显式直接进行写锁 然后再通过循环再试 } } } finally { sl.unlock(stamp); //释放读锁或写锁 } } }
StampedLock は ReentrantReadWriteLock よりも安価であり、消費量が少ないことを意味します。
StampedLockとReadWriteLockの性能比較
下の図は、ReadWritLockと比較して、1スレッドの場合、読み取り速度が約4倍、書き込み速度が1倍であることを示しています。下の図は、6つのスレッドで読み取りパフォーマンスが数十倍、書き込みパフォーマンスも10倍近くであることを示しています:
下の図はスループットの向上を示しています:概要
1. 同期は、一部の監視ツールを通じて監視できるだけでなく、コードの実行中に例外が発生したときに、JVM によって自動的に解放されます。 lock;
2 、 ReentrantLock 、 ReentrantReadWriteLock 、および StampedLock はすべて object レベルのロックです。
3 には unLock() を入れる必要があります。特に読み取りスレッドが増加するシナリオでは、StampedLock には複雑な API があり、競合相手が少ない場合には、同期が行われます。 a 優れた汎用ロック実装
6. スレッドの増加が予測できる場合、ReentrantLock は優れた汎用ロック実装です。
以上がJava8 の新機能の解釈 --StampedLockの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。