- PR -

synchronizedについて

1
投稿者投稿内容
cowboy
会議室デビュー日: 2007/01/15
投稿数: 2
投稿日時: 2007-09-24 22:40
synchronized修飾子は、あるオブジェクトobjに対して、メソッドmが呼ばれている間、
他のスレッドがobjに対してmを実行することをブロックする機能、ということなのですが、
次の、二つの違いがわかりません。どなたかこの違いをご教授ください。
以下のように、runメソッドにsynchronized修飾子をつけて、
billを「0」にして「1」にしてを繰り返すだけなのですが、
以下のように、オブジェクトをfor文の外側で生成して
Threadに代入すれば、うまくいくのですが、最後の3行を
---------------------------------------------------
for(int k = 0; k < 20; k++){
new Thread (new Staff(cashbox)).start();
---------------------------------------------------
とThreadクラスにオブジェクトをそのまま代入するとうまくいきません。
下の3行ではstaffという1つのオブジェクトに対して複数のスレッドがつくられ、
上の2行では複数のオブジェクトがつくられてしまうということなのかと考えるのですが、下の3行でもsynchronizedをとると、うまくいきません。
下の3行ではstaffという1つのオブジェクトに、
何回もrunメソッドを実行しているということなのでしょうか?
だとしたら、逆に2行のほうでは、それぞれ別のオブジェクトがつくられているので、
-18なったりしないのではないかと、こんがらがっています。
どなたがずばっと、ご教授おねがいします。


class Cashbox{int bill = 1;}

class Staff implements Runnable{
Cashbox cashbox;
Staff(Cashbox cashbox){this.cashbox = cashbox;}
public synchronized void run(){
try {
cashbox.bill--;
System.out.println("Borrow = " + cashbox.bill);
Thread.sleep(1000);
cashbox.bill++;
System.out.println("Return = " + cashbox.bill);
} catch (InterruptedException e) {}
}
}

public class Test {
public static void main(String[] args) {
Cashbox cashbox = new Cashbox();
Staff staff = new Staff(cashbox);
for(int k = 0; k < 20; k++){
new Thread (staff).start();
}
}
}
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-09-24 23:35
引用:

cowboyさんの書き込み (2007-09-24 22:40) より:
下の3行ではstaffという1つのオブジェクトに対して複数のスレッドがつくられ、
上の2行では複数のオブジェクトがつくられてしまうということなのかと考えるのですが、下の3行でもsynchronizedをとると、うまくいきません。
下の3行ではstaffという1つのオブジェクトに、
何回もrunメソッドを実行しているということなのでしょうか?


そうです。Javaの言語レベルの話です。
ループ中で毎回newしていれば当然ですよね?

引用:

だとしたら、逆に2行のほうでは、それぞれ別のオブジェクトがつくられているので、
-18なったりしないのではないかと、こんがらがっています。


Staff#cashboxはどちらの場合でも共有しているからです。
new Thread (new Staff(new Cashbox())).start();
とすれば結果が変わります。

質問の範囲からは外れますが、
通常はこのような場合にStaff#run()はsynchronized修飾しません。
共有されるリソース(この場合はcashbox)を同期化して保護します。

例えば、Staff#run()内で
synchronized (cashbox) {
 cashbox.bill--;
}
としたり、

CashboxにborrowBill()やreturnBill()を追加して
それぞれをsynchronized修飾して保護したりします。

#ただし、このような場合に
#synchronized (cashbox) {
# cashbox.bill--;
#}
#System.out.println("Borrow = " + cashbox.bill);
#なんてコードにすると正しい結果にならなくなるので注意しましょう。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2007-09-24 23:38
こんばんは。

synchronized修飾子が何に対してロックしようとしているかを理解すれば混乱が解けるとおもいます。
インスタンス・メソッドの場合、synchronizedキーワードはオブジェクトをロックし、メソッドやコードをロックしないということを理解する

cowboy
会議室デビュー日: 2007/01/15
投稿数: 2
投稿日時: 2007-09-24 23:52
あしゅさん
Tdnr_Symさん
ご教授いただきましてありがとうございます。
1

スキルアップ/キャリアアップ(JOB@IT)