凪瀬 Blog
Programming SHOT BAR

目次

Blog 利用状況
  • 投稿数 - 260
  • 記事 - 0
  • コメント - 46913
  • トラックバック - 192
ニュース
広告
  • Java開発者募集中
  • 経歴不問
  • 腕に自信のある方
  • 富山市内
  • (株)凪瀬アーキテクツ
アクセサリ
  • あわせて読みたい
凪瀬悠輝(なぎせ ゆうき)
  • Java技術者
  • お茶好き。カクテル好き。
  • 所属は(株)凪瀬アーキテクツ
  • Twitter:@nagise

書庫

日記カテゴリ

 

前のエントリで激しい議論が続いていますが、置いてきぼりをくらって バーカンウターで退屈そうにしていらっしゃるお客様のために、基礎講座を。

synchronizedの基本

同時に複数の人が編集作業をすると、あっというまにぐちゃぐちゃになってしまいます。 さっきまで10と書いてあったから、そこに1を足して11を書き込もう、としたらすでに値が12になっていた…。 そこでまぁいいや、と11と書き込むと、最後になって数字の辻褄があわなかったりするわけです。

マルチスレッドでの同期の問題のひとつはここにあります。
a += 1;
という単純な式でさえ、実際にはaを読み出し、1を足し、格納するというステップから成っています。
その間に他のスレッドに読み出され、別の値を格納されたりするわけです。

「1度にいじるのはひとりだけにしてくれ!」そういいたくなりますね。たとえばここに、ボールをひとつ用意します。 このボールを手にしている人だけが、編集をできるというルールを定めましょう。
もちろん、編集が終わったらボールは返します。こうすることで、編集がちょうど並列にされることを防げます。

Javaではこれをsynchronizedブロックで表現します。

  synchronized(lock) {
    // 一度に一人しか触れない部分
  }

synchronizedの後ろの括弧にはObjectのインスタンスを渡します。 このインスタンスが先ほどのボールの役割をします。 Objectのインスタンスであれば、なんでも構いませんが、 複数のsynchronizedブロックの同期を取る際には おなじボールを用いるようにしなければなりません。
ボールが違えば別々に処理できてしまいます。 どことどこが一緒に処理してはいけない場所なのか考えて、ボールを配しなければなりません。
このボールをロックオブジェクトといいます。

ここでsynchronizedってメソッドの修飾子じゃなかったっけ? という人がおられるのではないでしょうか。
メソッドの修飾キーワードとして書いた場合は暗黙にロックオブジェクトが決められます。

  /** メソッドにキーワードを設定 */
  public synchronized void hoge() {
    // ...
  }
  /** synchronizedブロック */
  public void hoge() {
    // thisオブジェクトでのロックと同じ
    synchronized (this) {
      // ...
    }
  }
  /** メソッドにキーワードを設定 */
  public static synchronized void staticHoge() {
    // ...
  }
  /** synchronizedブロック */
  public void staticHoge() {
    // 自身のclassオブジェクトでのロックと同じ
    synchronized (Hoge.class) {
      // ...
    }
  }

このように、インスタンスメソッドの場合はthisオブジェクトをロックオブジェクトにしたのと同じ、 staticメソッドの場合は classオブジェクトをロックオブジェクトにしたのと同じとなります。
同期の際にはロックオブジェクトが何かを常に意識しなくてはなりません。 慣れないうちは面倒でもsynchronizedブロックで記述するようにした方がよいでしょう。

投稿日時 : 2007年8月22日 0:17
コメント
  • # re: Javaの並列処理の基本
    黒龍
    Posted @ 2007/08/22 11:17
    thisでのロックは不味いですものね。とはいえそれと同じくらい自身で用意したobject以外でのロックも不味いわけですが。
  • # waitについてのまとめ
    凪瀬 Blog
    Posted @ 2007/08/22 11:46
    waitについてのまとめ
  • # re: Javaの並列処理の基本
    凪瀬
    Posted @ 2007/08/22 12:39
    thisのロックでも構わんのですが、防衛的なプログラムをするならthisは避けたほうがいいでしょうね。
    thisてのは当然外から参照できるので、外部で同期されたりすると調子が狂う。
    privateなフィールドにObjectをnewしてロックオブジェクトとして使う方が安全ですが、
    継承階層を考慮に入れたクラスの場合はもっと複雑なことになります…。
タイトル
名前
Url
コメント