3

一般的な例外の知恵、特にJavaでのチェックされた例外とチェックされていない例外の使用について多くのことが書かれていますが、アプリケーションの終了ではなく、スレッドの終了をデフォルトのポリシーにするという決定の防御に興味があります。 C++での方法。この選択は私には非常に危険なようです。プログラマーがランダムに計画しなかった条件により、スタックトレースをログに記録した後、プログラムの一部が停止しますが、残りのプログラム兵士は断固としてオンになります。何がうまくいかない可能性がありますか?私の直感と経験によると、ここでは多くのことがうまくいかない可能性があり、デフォルトのポリシーは、それを選択する特定の理由がある人だけが特別に選択する必要がある種類のものです。このような一見大きな欠点があるこの戦略の利点は何ですか?私はリスクを過大評価していますか?

編集:これまでの回答に基づいて、私は自分が認識している危険性の説明にもっと集中する必要があると感じています。共有状態を更新するために、複数のスレッド(スレッドプールなど)を使用するアプリケーションの場合について話しています。このポリシーはシングルスレッドアプリケーションでは問題にならないことを認識しています。

EDIT2:Thread.stop()メソッドが非推奨になった理由の説明から、言語メンテナの間でこれらのリスクが認識されていることがわかります(ここにあります:http://docs.oracle.com/javase/7/docs /technotes/guides/concurrency/threadPrimitiveDeprecation.html)。キャッチされない例外が原因でスレッドが予期せず停止した場合も、まったく同じ問題が当てはまります。彼らは、スレッドが停止したときにすべてのモニターが自動的にロック解除されるようにJVMを設計している必要があります。これは、実装の選択としては不適切なようです。モニターがロックされているときにスレッドが停止するということは、プログラム全体が停止する必要があることを示しているはずです。これは、一部の共有状態では、代替手段が内部の不整合であることがほぼ確実だからです。

4

3 に答える 3

1

この問題について同僚と話し合い、これまでに受け取った回答を検討した結果、ここで仮説を立てました。フィードバックを求めたいと思います。

この動作をデフォルトにするという決定は、言語の初期の開発と初期の環境を定義した哲学に根ざしていると思います。

元の哲学の一部として、プログラマー/デザイナーはチェック例外を使用することが期待されていました。言語は、メソッド呼び出しによって発行される可能性がある (つまり、メソッド定義で宣言されている) チェック例外を呼び出し元のメソッドで処理する必要があることを強制します。または、「公式に」責任をより高いレベルの呼び出し元に渡すと宣言されます。一般的な慣行は、チェック済み例外の使用から急激に離れており、実際に最も一般的に発生する例外の 1 つである NullPointerException がチェックされていないという事実は言うまでもありません。この結果、プログラマーは、どのメソッド呼び出しでも非チェック例外が生成される可能性があると想定する必要があります。これに対する当然の帰結として、並行コンテキストで共有データを更新するコードは、完全に正しくするために、これらの更新のトランザクション セマンティクスを実装する必要があります。私の経験では、ほとんどの開発者は、クリティカル セクションを同期で管理する際のデッドロックの回避など、マルチスレッド開発の基本を理解していても、これを実際には理解していません。デフォルトのキャッチされない例外ハンドラーの動作は、その影響をマスクすることによって問題を悪化させます。C++ では、キャッチされない例外が原因で共有状態が破損しても問題ありません。これは、いずれにしてもプログラムが停止しているためです。しかし、Java では、プログラムは、正しく動作しなくなる可能性が非常に高いという事実にもかかわらず、可能な限り最善を尽くします。クリティカル セクションを同期で管理する際のデッドロックの回避など、マルチスレッド開発の基本を理解していても、これを本当に理解することはできません。デフォルトのキャッチされない例外ハンドラーの動作は、その影響をマスクすることによって問題を悪化させます。C++ では、キャッチされない例外が原因で共有状態が破損しても問題ありません。これは、いずれにしてもプログラムが停止しているためです。しかし、Java では、プログラムは、正しく動作しなくなる可能性が非常に高いという事実にもかかわらず、可能な限り最善を尽くします。クリティカル セクションを同期で管理する際のデッドロックの回避など、マルチスレッド開発の基本を理解していても、これを本当に理解することはできません。デフォルトのキャッチされない例外ハンドラーの動作は、その影響をマスクすることによって問題を悪化させます。C++ では、キャッチされない例外が原因で共有状態が破損しても問題ありません。これは、いずれにしてもプログラムが停止しているためです。しかし、Java では、プログラムは、正しく動作しなくなる可能性が非常に高いという事実にもかかわらず、可能な限り最善を尽くします。

環境要因は、言語が最初に開発されたときはシングルスレッド プログラムが標準であった可能性が高いため、デフォルトの動作が正しいものとして偽装されたことです。マルチコア アーキテクチャの台頭とスレッド プールの使用の増加により、脅威がより広範に公開されており、不変オブジェクトの使用などの一般的に適用されるアプローチでは、問題を解決することしかできません (一部の人へのヒント: ConcurrentMap はおそらくあなたほど安全ではありません)。だと思います)。これまでの私の経験では、このリスクを否定する人は、コードの実際の安全要件に対して十分に偏執的ではありませんが、私が間違っていることを証明したいと思います.

キャッチされなかった例外ハンドラーを変更してプログラムを終了させることは、ほとんどの開発組織で必要とされる標準的な手順であるべきだと思います。少なくとも、受信入力に基づいて共有状態を更新することが知られているスレッド プールに対しては、これを行う必要があります。

于 2013-01-30T04:55:57.893 に答える
1

@BD、ここで説明していないため、これについてあなたの経験が何を言っているのかわかりません。しかし、開発者として私が経験したことは次のとおりです。

  1. 一般に、DB の再起動やファイルの置き換えなどの理由でコンポーネントの 1 つが (一時的または永続的に) 失敗した場合、アプリケーションを失敗させることはお勧めできません。たとえば、新しいタイプの下取りシステムを導入して何らかの問題が発生した場合、アプリケーションをシャットダウンすべきではありません。

  2. Web/アプリケーション サーバーなどのアプリケーションは、デプロイのいずれかが異常な例外をスローしている場合でも、引き続き動作し、ユーザーに応答できる必要があります。

例外に関する懸念のとおり、通常、すべてのアプリケーションには、CPU/ディスク/RAM の使用状況やログのエラーなどの状態を監視し、それに応じてアラートを発する状態監視システムがあります。

これで混乱が解消されることを願っています。

于 2013-01-24T03:22:19.780 に答える
0

通常の(GUIなし、コンテナーなし)アプリケーションは、キャッチされない例外で終了します(デフォルトの動作は問題ありません)。

GUIベースのアプリケーションでは、エラーメッセージを表示し、エラーをより便利に処理できると便利です。たとえば、いくつかの追加情報を含む欠陥レポートを送信できます。

アプリケーションの終了を含む可能性のあるスレッド固有の例外ハンドラーを提供することで、動作を完全に変更できます。

ここにいくつかの有用なメモがあります

于 2013-01-24T05:26:14.367 に答える