2

呼び出されたメソッドがdoSomething()あり、このメソッドをマルチスレッド アプリケーションで使用したいとします (各サーブレットは HttpServlet から継承されます)。次の場合に競合状態が発生する可能性があるかどうか疑問に思っています。

  1. doSomething()静的メソッドではなく、値をデータベースに書き込みます。
  2. doSomething()静的メソッドですが、データベースに値を書き込みません。

アプリケーションの多くのメソッドが競合状態またはダーティな読み取り/書き込みにつながる可能性があることに気付きました。たとえば、 Poll System があり、投票操作ごとに、特定のメソッドがその投票の単一のセル値を次のように変更します。

[poll_id |              poll_data        ]
[1       | {choice_1 : 10, choice_2 : 20}]

JSP/サーブレット アプリはこれらの問題を単独で解決しますか? それとも、すべて自分で解決する必要がありますか?

ありがとう..

4

5 に答える 5

4

doSomething()実装方法と実際に何をするかによって異なります。データベースへの書き込みには、スレッドセーフではないJDBC 接続が使用されると想定しています。そのための推奨される方法は、ThreadLocalJDBC 接続を作成することです。

2 番目のケースについては、メソッドで何が起こっているかによって異なります。共有された変更可能な状態にアクセスしない場合、問題はありません。その場合、おそらく適切にロックする必要があります。これには、それらの変数への他のすべてのアクセスにロックを追加することが含まれる場合があります。

(これらのメソッドを としてマークするだけでsynchronizedは同時実行のバグは修正されないことに注意してください。doSomething()共有オブジェクトの値をインクリメントした場合、その変数へのすべてのアクセスはアトミック操作ではないため、synchronizedそうする必要があります。i++カウンター、使用できますAtomicInteger.incrementAndGet()。)

于 2010-05-04T18:21:14.260 に答える
3

サーブレット API が魔法のように同時実行性を問題にしないわけではありません。

データベースに書き込むときは、永続化レイヤーの同時実行戦略によって異なります。悲観的ロック、楽観的ロック、後攻?「データベースに書き込む」ときは、処理方法を決定する必要があることがたくさんあります。2 人が同時にボタンをクリックしたときに何が起こるようにしたいですか?

doSomething を静的にしても、この問題にはあまり関係がないようです。そこで起こっているのは、関連する部分です。静的変数を変更していますか? はい、競合状態が発生する可能性があります。

于 2010-05-04T18:24:10.163 に答える
2

サーブレット API は、並行性の問題を解消するために何もしません。サーブレットで synchronized キーワードを使用するなどのことは、基本的にスレッドを一度に 1 つずつ処理するように強制し、複数のユーザーに迅速に応答する能力を台無しにするため、悪い考えです。

Spring または EJB3 を使用する場合、どちらもスレッドローカル データベース接続とトランザクションを指定する機能を提供します。あなたは間違いなくそれらの1つをチェックする必要があります.

于 2010-05-04T18:30:14.733 に答える
2

ケース 1、サーブレットはデータベースにアクセスするコードを使用します。データベースには、活用すべきロック メカニズムがあります。これには 2 つの重要な理由があります。データベース自体が、そのデータの読み取りと書き込みを行う他のアプリケーションから使用される可能性があるため、アプリがそれ自体との競合に対処するには十分ではありません。また、独自のアプリケーションを、拡張されたクラスター化された Web コンテナーにデプロイすることもできます。このコンテナーでは、コードの複数のコピーが別々のマシンで実行されます。

そのため、データベースのロックを処理するための標準的なパターンは多数あります。悲観的ロックと楽観的ロックについて読む必要があるかもしれません。

サーブレット API と JBC 接続プーリングは、いくつかの有用な保証を提供するため、Java 同期を使用せずにサーブレット コードを記述できます (概念上、変数がメソッド スコープ内にある場合)。

   Start transaction (perhaps implicit, perhaps on entry to an ejb)
   Get connection to  DB ( Gets you a connection from pool, associated with your tran)
   read/write/update code
   Close connection (actually keeps it for your thread until your transaction commits)
   Commit (again maybe implictly)

したがって、唯一の本当の問題は、DB 内の競合に対処することです。上記のすべては、最近では JPA などを使用してかなり適切に行われる傾向がありますが、その裏では多かれ少なかれ何が起こっているのでしょう。

ケース 2: 静的メソッド。これはおそらく、すべてをメモリ構造に保持していることを意味します。これは (ある種のリモート呼び出しを禁止する)、単一の JVM と、独自のロックを管理することを意味します。JVM またはマシンがクラッシュすると、データが失われると思います。データに関心がある場合は、DB を使用することをお勧めします。

または、まったく別のアプローチはどうでしょうか。サーブレットは、永続的な JMS キューにメッセージを書き込むことによって、単に「投票」を記録します。他のプロセスがキューから投票を取得し、それらを追加します。この方法では、有権者にすぐにフィードバックを提供することはできませんが、ユーザーのエクスペリエンスを実際の (同様のシナリオで) 非常に複雑な処理から切り離します。

于 2010-05-04T19:06:07.710 に答える
0

あなたの問題に対する最善の解決策は、「同期」キーワードのようなものを使用して待機/通知することです!

于 2010-05-04T18:15:00.500 に答える