Java マルチスレッド プログラミングでは、スレッド セーフは非常に重要な概念です。複数のスレッドが同時に実行されるときに正しい動作を維持するプログラムは、スレッドセーフであると言われます。この記事では、Java でスレッドの安全性を確保できる一般的な実装アイデアをいくつか紹介します。
synchronized キーワードは、Java のスレッド セーフティの問題を解決する最も基本的な方法です。これにより、コード ブロックが確実に安全であることが保証されます。アトミックに実行する方法。 synchronized キーワードは、インスタンス メソッド、静的メソッド、およびコード ブロックを変更するために使用できます。これは、synchronized
public class Counter { private int count; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } }
を使用して変更されたインスタンス メソッドのサンプル コードです。上記のコードでは、increment() メソッドと getCount() メソッドが synchronized によって変更されており、一度に 1 つのスレッドのみがアクセスできるようになります。このアプローチは単純ですが、これらのメソッドにアクセスできるのは一度に 1 つのスレッドだけであるため、比較的非効率的です。
Java の ReentrantLock クラスは、synchronized よりも柔軟なスレッド同期メカニズムを提供します。 ReentrantLock は再入可能であり、ロックを待機しているスレッドに割り込み、tryLock() メソッドを通じてロックの取得を試みることができます。これは、ReentrantLock を使用してスレッド セーフを実現するためのサンプル コードです。
import java.util.concurrent.locks.ReentrantLock; public class Counter { private int count; private ReentrantLock lock = new ReentrantLock(); public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount() { lock.lock(); try { return count; } finally { lock.unlock(); } } }
上記のコードでは、lock.lock() メソッドを呼び出すことによってロックが取得され、lock.unlock() メソッドを呼び出すことによってロックが解放されます。 ) 方法。 ReentrantLock を使用するときに注意する必要があるのは、ロックを正しく解放できるように、ロックの取得と解放のロジックを try-finally ブロックに配置する必要があることです。
Java では、ConcurrentHashMap はスレッドセーフなハッシュ テーブルの実装です。 ConcurrentHashMap は、セグメント ロック メカニズムを使用して、ハッシュ テーブル全体を複数のセグメントに分割し、異なるセグメントの要素に複数のスレッドから同時にアクセスできます。以下は、スレッド セーフを実現するために ConcurrentHashMap を使用するサンプル コードです。
import java.util.concurrent.ConcurrentHashMap; public class Counter { private ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>(); public void increment(String key) { map.put(key, map.getOrDefault(key, 0) + 1); } public int getCount(String key) { return map.getOrDefault(key, 0); } }
上記のコードでは、ConcurrentHashMap はカウンターの値、map.put() および map.getOrDefault() を格納するために使用されます。メソッドは、カウンターの値を更新および取得するために使用されます。 ConcurrentHashMap はスレッドセーフであるため、この実装により、複数のスレッドが同時にアクセスしたときにカウンター値が正しいことが保証されます。
Java では、Atomic クラスは一連のアトミック操作を提供し、操作がアトミックな方法で実行されることを保証します。アトミック クラスには、AtomicBoolean、AtomicInteger、AtomicLong などが含まれます。以下は、スレッド セーフを実現するための AtomicInteger の使用を示すサンプル コードです。
import java.util.concurrent.atomic.AtomicInteger; public class Counter { private AtomicInteger count = new AtomicInteger(); public void increment() { count.incrementAndGet(); } public int getCount() { return count.get(); } }
上記のコードでは、AtomicInteger を使用してカウンターの値を保存し、count.incrementAndGet() メソッドを使用して更新します。カウンタの値。 AtomicInteger はスレッドセーフであるため、この実装により、複数のスレッドが同時にアクセスしたときにカウンター値が正しいことが保証されます。
ThreadLocal クラスを使用すると、各スレッドが変数の独自のコピーを持つことができます。複数のスレッドが同時に実行される場合、各スレッドは独自の変数のコピーを独立して操作できます。したがって、スレッドの安全性の問題を回避できます。以下は、ThreadLocal を使用してスレッド セーフを実現するサンプル コードです。
public class Counter { private ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0); public void increment() { threadLocal.set(threadLocal.get() + 1); } public int getCount() { return threadLocal.get(); } }
上記のコードでは、ThreadLocal クラスを使用してカウンターの値、threadLocal.set() および threadLocal.get を格納します。 () メソッドは、カウンター値の更新と取得に使用されます。複数のスレッドが同時にアクセスしたときにカウンタ値が正確であることを保証するために、変数の独立したコピーを持つように各スレッドを設定します。
この記事では、synchronized キーワード、ReentrantLock クラス、ConcurrentHashMap クラス、Atomic クラス、ThreadLocal クラスなど、Java でスレッド セーフを実現するためのいくつかの方法を紹介します。実際のニーズに応じて、適切な方法を選択する必要があり、それぞれの方法には独自の特徴と適用可能なシナリオがあります。システムのパフォーマンスと同時実行性を最適化するために、複数の方法を組み合わせてスレッド セーフを実現できます。
以上がJava でのスレッド セーフ実装のアイデアの紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。