ホームページ  >  記事  >  Java  >  Java 関数の悲観的ロックと楽観的ロックはどのようにしてスレッド セーフを実現するのでしょうか?

Java 関数の悲観的ロックと楽観的ロックはどのようにしてスレッド セーフを実現するのでしょうか?

WBOY
WBOYオリジナル
2024-05-04 16:51:02549ブラウズ

Java 関数でスレッドの安全性を実現する 2 つの方法: 悲観的ロック: データにアクセスする前にロックを取得し、他のスレッドによる同時アクセスを防ぎ、データの一貫性を確保します。 (synchronized キーワード) オプティミスティック ロック: トランザクションの終了時にデータを検証し、同時実行性を向上させるためにデータが変更された場合はトランザクションをロールバックします。 (java.util.concurrent.atomic パッケージの Atomic クラス)

Java 函数中的悲观锁与乐观锁如何实现线程安全?

Java 関数の悲観的ロックと楽観的ロックはどのようにしてスレッド セーフを実現するのでしょうか?

スレッドの安全性はマルチスレッド環境にとって非常に重要であり、同時にデータにアクセスする際のデータの整合性と一貫性を確保します。 Java では、ペシミスティック ロックとオプティミスティック ロックがスレッド セーフを実現する 2 つの主要なメカニズムです。以下では、それらがどのように実装されるかを検討し、実践的な例を示します。

悲観的ロック

悲観的ロックは、データがいつでも他のスレッドによって変更される可能性があるという前提に基づいています。したがって、データにアクセスするとすぐにロックを取得し、ロックが解放されるまで他のスレッドがデータにアクセスできないようにします。悲観的ロックの利点は、データの整合性を確保できることですが、欠点は、ロックの競合やデッドロックが発生する可能性があることです。

synchronized キーワードは、Java で悲観的ロックを実装する一般的な方法です。コード ブロックをクリティカル セクションとしてマークし、ロックを取得したスレッドのみがコード ブロックに入ることができます。

public class Counter {

    private int count;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

オプティミスティック ロック

オプティミスティック ロックは、スレッドがデータにアクセスするときに、そのデータが他のスレッドによって変更される可能性は低いという前提に基づいています。トランザクションの終了時にのみデータを検証し、データが変更されている場合はトランザクションをロールバックします。オプティミスティック ロックの利点は、同時実行性を向上できることですが、欠点は、データが変更されるとトランザクションが失敗する可能性があることです。

Java では、java.util.concurrent.atomic パッケージのアトミック クラスでオプティミスティック ロックを実装できます。アトミック クラスの操作はアトミックであるため、データへの同時アクセスの正確性が保証されます。

import java.util.concurrent.atomic.AtomicInteger;

public class Counter {

    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

実際のケース: マルチスレッド銀行口座

実際のシナリオでの悲観的ロックと楽観的ロックの適用を実証するために、マルチスレッド銀行を検討します。アカウント。

  • 悲観的ロックの実装:
public class BankAccount {

    private int balance;

    public synchronized void withdraw(int amount) {
        if (balance >= amount) {
            balance -= amount;
        }
    }

    public synchronized int getBalance() {
        return balance;
    }
}
  • 楽観的ロックの実装:
import java.util.concurrent.atomic.AtomicInteger;

public class BankAccount {

    private AtomicInteger balance = new AtomicInteger(0);

    public void withdraw(int amount) {
        while (true) {
            int currentBalance = balance.get();
            if (currentBalance >= amount) {
                if (balance.compareAndSet(currentBalance, currentBalance - amount)) {
                    break;
                }
            } else {
                break;
            }
        }
    }

    public int getBalance() {
        return balance.get();
    }
}

オプティミスティック ロックを使用して、引き出し時に現在の残高を取得し、compareAndSet を使用して引き出し金額をアトミックに減算しようとします。残高が不十分な場合、操作は失敗し、スレッドは再試行されます。

悲観的ロックまたは楽観的ロックの選択

悲観的ロックまたは楽観的ロックの選択は、特定のシナリオに応じて異なります。データへの同時アクセスがまれである場合、またはデータの一貫性が重要な場合は、悲観的ロックの方が適切です。データへの同時アクセスが頻繁で、データの一貫性によってある程度の妥協が許容される場合は、楽観的ロックの方が適切です。

以上がJava 関数の悲観的ロックと楽観的ロックはどのようにしてスレッド セーフを実現するのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。