
スレッドの安全性を文書化することの重要性
- クラス契約の一部: クラスが同時アクセスをどのように処理するかは、クライアントにとって非常に重要です。
間違った仮定のリスク:
- 同期が不十分または過剰です (項目 78 および 79)。
- プログラムの動作に重大なエラーがあります。
指標として同期を使用する場合の問題
- 実装の詳細: パブリック API の一部ではありません。
- 単純化した見方: スレッド セーフは二値的なプロパティ (すべてか無か) ではありません。さまざまなレベルがあります。
スレッドの安全性レベル
不変:
- それらは定数のように動作します。
- 外部同期は必要ありません。
- 例: String、Long、BigInteger。
無条件にスレッドセーフ:
- 変更可能なインスタンスですが、十分な内部同期が行われています。
- 追加の同期なしで安全に同時使用できます。
- 例: AtomicLong、ConcurrentHashMap。
条件付きスレッドセーフ:
- 無条件と似ていますが、一部のメソッドでは外部同期が必要です。
- 例: Collections.synchronized。反復時に同期が必要です。
Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>());
synchronized (syncMap) {
for (String key : syncMap.keySet()) {
// Iteração segura
}
}
ログイン後にコピー
スレッドセーフなし:
- 外部同期を使用するメソッドを含める必要があります。
- 例: ArrayList、HashMap。
スレッドに対して敵対的:
- 外部同期を使用しても安全ではありません。
- 通常は、同期せずに静的データを変更するなどのエラーの結果です。
スレッドの安全性を文書化する方法
Javadoc の明確なドキュメント:
- 提供されるセキュリティのレベル。
- 外部同期を必要とするメソッドまたはシーケンス。
- 使用する特定のロック。
反復のための同期ドキュメントの例:
/**
* É necessário sincronizar manualmente ao iterar sobre as views deste mapa.
* Exemplo:
* synchronized (map) {
* for (Object key : map.keySet()) {
* // Iteração segura
* }
* }
*/
ログイン後にコピー
プライベートロックオブジェクトの使用
利点:
- クライアントとサブクラスからの干渉を回避します。
- 将来的には、より高度な同時実行制御が可能になります。
例:
private final Object lock = new Object();
public void threadSafeMethod() {
synchronized (lock) {
// Código protegido
}
}
ログイン後にコピー
最終フィールド: ロック オブジェクトへの誤った変更から保護します。
継承用のクラスを設計するときの注意
- サブクラスと基本クラスで同じロックを使用すると、干渉が発生する可能性があります。
- 競合を避けるためにプライベート ロックを優先します。
最終まとめ
- クラスのスレッド セーフ性を常に文書化します (テキストまたはメモを使用)。
- ドキュメントへの同期モディファイアだけに依存しないでください。
- 無条件にスレッドセーフなクラスの場合は、プライベート ロック オブジェクトの使用を検討してください。
- 条件付きスレッドセーフ クラスは、どのロックをいつ使用するかを指定する必要があります。
以上が項目 スレッドの安全性を文書化するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。