同期の使用 - 1

「こんにちは、アミーゴ!」

「はい、ここにいます、ここにいます。」

今日は実際に同期を使う方法についてお話します。

「プログラムに多数のオブジェクトとスレッドがある場合、複数のスレッドが同じオブジェクトを同時に処理することがよくあります。その際、スレッドは互いに干渉します。」

「はい、それはもう知っています。」

「それでは、複数のスレッドからアクセスされているオブジェクトがあるとします。問題を回避するには、2 つのことを行うことができます。」

「1 つ目は、同期ブロックを使用して、オブジェクトがアクセスされるすべての場所をラップすることです。しかし、プログラマーが同期ブロックを使用せずにオブジェクトに直接アクセスするコードを作成した場合、このアプローチは機能しない可能性があります。」

「したがって、ほとんどの場合、オブジェクトをスレッドセーフにする 2 番目のアプローチが使用されます。」「言い換えれば、同期メカニズムはオブジェクト自体に組み込まれています。つまり、メソッドの同期を宣言したり、メソッド内のコードを同期ブロックでラップしたりするのです。」

「では、複数のスレッドから使​​用する可能性のあるオブジェクト、つまりプログラム内のほぼすべてのオブジェクトは、スレッドセーフにする必要があるのでしょうか?」

「一般的にはそうです。実際には、プログラム内のすべてのオブジェクトが別のスレッドで使用されるわけではありませんが、通常はたくさんのオブジェクトが使用されます。したがって、スレッドのコードを書き始めてそこからさまざまなオブジェクトにアクセスするとき、各メソッド呼び出しで「この電話は安全ですか?」と自問する必要があります。

"安全?"

「スレッドセーフ。つまり、複数のスレッドから安全に呼び出すことができます。」

「ここにいくつかの例を示します。別のスレッドからアクセスされる String オブジェクトがあるとします。すでに覚えているはずですが、他のすべてのプリミティブ型と同様に、String は不変です。これは、オブジェクトが作成後に変更されないことを意味します。 . これは、そのようなオブジェクトを「壊す」ことは不可能であることを意味します。すべての不変オブジェクトはスレッドセーフです。」

「そうですね、その方が物事は楽になりますよ。」

「次に、変更可能な文字列が必要だとします。」

「ああ、覚えています。そのような文字列には StringBuffer と StringBuilder の 2 種類があります。StringBuffer は StringBuilder に似ていますが、そのメソッドはすべて同期されています。スレッドセーフでもありますか?」

「はい。複数のスレッドから StringBuilder オブジェクトにアクセスする必要がある場合は、それを StringBuffer に置き換える必要があります。そうしないと、遅かれ早かれスレッドが同時にオブジェクトを変更し、«ブレーク» します。」

「別のスレッドからアクセスされているオブジェクトが自分のクラスのオブジェクトである場合はどうなりますか? この場合も、そのメソッドに synchronized を追加する必要がありますか?」

「はい。このルールに従うのが最善です。別のスレッドからアクセスされるすべてのオブジェクトはスレッドセーフでなければなりません。」

「そうですか。こんなに大変だとは思いませんでした。ありがとう、エリー」

「どういたしまして。ディエゴがいくつかの簡単なタスクを与えるときに、これらのヒントが役立つことを願っています。☺」