春からJavaMailSenderImplを使用して、Webアプリケーションで電子メールを送信しています。私はこれのインスタンスを1つだけ作成しました(実際には、豆を使用して作成され、シングルトンである別のオブジェクトによって使用されます)。JavaMailSenderImplはスレッドセーフですか?
JavaMailSenderImplはスレッドセーフなのですか?私のアプリでは、複数のスレッドが同時にmailSenderを使用している場合、競合状態につながるでしょうか?
春からJavaMailSenderImplを使用して、Webアプリケーションで電子メールを送信しています。私はこれのインスタンスを1つだけ作成しました(実際には、豆を使用して作成され、シングルトンである別のオブジェクトによって使用されます)。JavaMailSenderImplはスレッドセーフですか?
JavaMailSenderImplはスレッドセーフなのですか?私のアプリでは、複数のスレッドが同時にmailSenderを使用している場合、競合状態につながるでしょうか?
はいJavaMailSenderImpl
はスレッドセーフですが構築されています。
実際の作業を行うdoSend
の方法を見てください。これにはメソッドローカル変数のみが含まれています(各呼び出しスレッド/スタックには独自のインスタンスがあります)。 (同じことがいくつかの機能を追加するsend
メソッドにも当てはまります)。
getSession
のようなメソッドはです。したがって、そのスレッドには1つのスレッドしかアクセスできません。
スレッドセーフな最大の理由は、(ほとんど)変更可能な共有状態がなく、という単一の変更可能な共有状態(Session
)があるということです。
次に、プロダクションシステムで12年以上シングルトンで使用しており、並行性に問題はありませんでした。そして、私たちは非常に並行したアプリケーションでも使用しました。 (また、Spring BatchとSpring Integrationのような他のフレームワークコンポーネントがJavaMailSender
APIを使用する方法でもあります)。
[フィールドロード](https://github.com/spring-projects/spring-framework/blob/master/spring-context-support/src/main/java/org)の順序を見てください/springframework/mail/javamail/JavaMailSenderImpl.java#L491)。ユーザー名とパスワードは 'getSession'呼び出しの前にロードされるため、構築後のシンクポイントが存在していても、ここで発生する先行エッジはありません。 – SerCe
正しい...しかし、それは最初にやってはいけないことです...そして、私はそれが建設の後で使用することが安全だと述べています...単一のスレッドで春のブートストラップ。また、 'getUsername'と' getPassword'は一度呼び出され、その後はグローバルではなくローカルで使われます。同じことがフレームワークの他のクラスにも当てはまります(これらはすべて注釈を含みます:**このクラスのインスタンスは、一旦設定されるとスレッドセーフです**。)。 –
@ m-deinumしかし、 'connectTransport'は異なるスレッドから(' doSend'ごとに)複数回呼び出すことができます。したがって、そのスレッドがspring-bootstrapスレッドの前に開始した場合、 'beforeUpname'が存在しないため' getUsername'からnullを読み取ることができます。 (私はそれは非常に非現実的なケース、特にx86の場合は同意しますが、ここではJMMの正当性を証明することはできません) – SerCe
いいえ、そうではありません。
it hasソースコード内で同期していますが、ユーザー、パスワードなどのフィールドには同期アクセスがありません。したがって、あるスレッドでsetUsername
を呼び出すと、他のスレッドに対する可視性の保証はありません。
私は、春に1回だけオブジェクトを作成し、メールサーバー認証とjavaMailPropertiesに必要なすべてのフィールドを設定しています。私はそれらを再び変えない。オブジェクトが作成されると、複数のスレッド(桟橋)がメールを並行して送信します。問題になるのだろうか?私は具体的にメール送信部について尋ねています。 – kiran
[ここ](https://github.com/spring-projects/spring-framework/blob/master/spring-context-support/src/main/java/org/springframework/mail/javamail/JavaMailSenderImpl.java#sourcegraph&def = getSession&L151-156)、ゲッターは最初の同期ポイントの前に呼び出されるため、前の同期ポイントよりも前に呼び出されます。スレッドセーフ、 – SerCe
はい、一度構築するとスレッドセーフです。 –
@ M.Deinum私はソースコードを見ても同じと思ったが、分かりません。私がそれを受け入れることができるように、あなたは精巧に答えを加えてください。複数のスレッドがメールを同時にどのように送信できるかについて説明すると素晴らしいでしょう。 – kiran