コードの要点:オブジェクトのロックと同期

このQ&Aのポイント
  • 上記のコードでは、オブジェクトのロックと同期が行われています。
  • countLockを使用して、複数のスレッドが同時にcountを変更できないようにしています。
  • synchronizedブロック内では、countが1であることを確認しています。
回答を見る
  • ベストアンサー

コードがよくわかりません。

コードがよくわかりません。 package rwlock; public class MyObj0 { private Object countLock = new Object(); private int count; private void enter() { synchronized(countLock) { count++; } } private void leave() { synchronized(countLock) { count--; } } public MyObj0() { count = 0; } public void refer() { enter(); Time.sleep(300); leave(); } public void update() { enter(); synchronized(countLock) { assert count == 1; } Time.sleep(500); leave(); } } 上のコードで private Object countLock = new Object();において、ObjectクラスのcountLockを作ったり private void enter() { synchronized(countLock) { count++; } } において、countLockをcountの前においたり、 synchronized(countLock) { assert count == 1; } で(countLock)がおいてある意味がわかりません。 何のためでしょうか? よろしくお願いいたします。

noname#182748
noname#182748
  • Java
  • 回答数1
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • tasoh
  • ベストアンサー率45% (19/42)
回答No.1

排他制御を行うためです 複数スレッドで、同じ変数をカウントアップしたりカウントダウンした時に 同じタイミングでやってしまい、結果の整合性がなくならないように カウントアップやカウントダウンをするときだけロックをかけるために、ロック用変数としてcountLockを生成しているのです。 参考URL↓ http://www.javaroad.jp/java_thread4.htm

noname#182748
質問者

お礼

返答ありがとうございます。おかげで助かりました。

関連するQ&A

  • javaの同期について

    javaの同期について package rwlock; public class App1 extends Thread { static private final int REFER = 0; static private final int UPDATE = 1; static private final int[] conf1 = { REFER, REFER, REFER, UPDATE }; static private final int[] conf2 = { REFER, UPDATE, REFER, REFER }; static private MyObj0 mo = new MyObj0(); // App1 + MyObj0 int id; private int[] conf; public App1(int id, int[] conf) { this.id = id; this.conf = conf; } public void run() { long tStart = Time.current(); for (int i = 0; i < conf.length; i++) { switch(conf[i]) { case REFER: mo.refer(); break; case UPDATE: mo.update(); break; default: assert false : "internal error"; } } if (id == 1) { Time.printElapsed(tStart); } } public static void main(String[] args) { App1 th1 = new App1(1, conf1); App1 th2 = new App1(2, conf2); th1.start(); th2.start(); } } public class MyObj0 { private Object countLock = new Object(); private int count; private void enter() { synchronized(countLock) { count++; } } private void leave() { synchronized(countLock) { count--; } } public MyObj0() { count = 0; } public void refer() { enter(); Time.sleep(300); leave(); } public void update() { enter(); synchronized(countLock) { assert count == 1; } Time.sleep(500); leave(); } において、updateの実行中は、他のスレッドでもupdateもreferも実行されないが、二つのスレッドで同時にreferは実行されうるという条件を満たすにはどうしたらよいでしょうか?updateにsynchronizedをつけてみましたが、referが同時に実行されてしまいました

    • ベストアンサー
    • Java
  • javaの同期について

    javaの同期について package rwlock; public class App1 extends Thread { static private final int REFER = 0; static private final int UPDATE = 1; static private final int[] conf1 = { REFER, REFER, REFER, UPDATE }; static private final int[] conf2 = { REFER, UPDATE, REFER, REFER }; static private MyObj0 mo = new MyObj0(); // App1 + MyObj0 int id; private int[] conf; public App1(int id, int[] conf) { this.id = id; this.conf = conf; } public void run() { long tStart = Time.current(); for (int i = 0; i < conf.length; i++) { switch(conf[i]) { case REFER: mo.refer(); break; case UPDATE: mo.update(); break; default: assert false : "internal error"; } } if (id == 1) { Time.printElapsed(tStart); } } public static void main(String[] args) { App1 th1 = new App1(1, conf1); App1 th2 = new App1(2, conf2); th1.start(); th2.start(); } } public class MyObj0 { private Object countLock = new Object(); private int count; private void enter() { synchronized(countLock) { count++; } } private void leave() { synchronized(countLock) { count--; } } public MyObj0() { count = 0; } public void refer() { enter(); Time.sleep(300); leave(); } public void update() { enter(); synchronized(countLock) { assert count == 1; } Time.sleep(500); leave(); } において、updateの実行中は、他のスレッドでもupdateもreferも実行されないが、二つのスレッドで同時にreferは実行されうるという条件を満たすにはどうしたらよいでしょうか?updateにsynchronizedをつけてみましたが、referが同時に実行されてしまいました。

    • ベストアンサー
    • Java
  • スレッド間の送受信のコードについて

    下記のコードは、(以前お教え頂きました)『synchronized』を使用した、スレッド間の 送受信のコードですが、その代わりに、Interruptとか、Thread.sleep()を使用した、 コードに変更してみたいと思います。 Q1)そのコードをお教え頂けないでしょうか? class T_thread { public static void main(String args[]) { new rcvInterrupt().start(); } } class genInterrupt extends Thread { private rcvInterrupt target; genInterrupt(rcvInterrupt targetx) { this.target = targetx; } public void run() { System.out.println("genInterupt start"); for (int i = 0; i < 10; i++) { while (!target.isWaited) { // rcvInterruptがsynchronizedブロックに入るまで待ち合わせ // これがないと連続してsynchronizedしてしまう可能性がある } synchronized (target) { target.notifyAll(); target.isWaited = false; System.out.println("notify"); } } } } class rcvInterrupt extends Thread { volatile boolean isWaited; public synchronized void run() { new genInterrupt(this).start(); for (int i = 0; i < 10; i++) { try { isWaited = true; wait(); System.out.println("get interrupt cnt=" + i); } catch (InterruptedException e1) { } } } } 以上

    • ベストアンサー
    • Java
  • デッドロックに関して1

    下記のサンプルソースは、デッドロックを起こすソース なのですが、 public class Deadlock extends Thread { public static Object l1 = new Object(); public static Object l2 = new Object(); private int index; public static void main(String[] a) { Thread t1 = new ThreadA(); Thread t2 = new ThreadB(); t1.start(); t2.start(); } private static class ThreadA extends Thread { public void run() { synchronized (l1) { System.out.println("スレッド1: l1に対するロックを取得"); try { Thread.sleep(10); } catch (InterruptedException e) {} System.out.println("スレッド1: l2のロックの開放待ち"); synchronized (l2) { System.out.println("スレッド1: l1、l2に対するロックを取得"); } } } } private static class ThreadB extends Thread { 文字数オーばーのため削除 } これを参考に、Junitでデッドロックを起こすサンプルを作りたいです。 MultithreadedTestCaseと ControllableTestThreadを使い サンプルを作りたいのですが、 英語が良くわからず苦戦しております。 なにか、よいアドバイスをいただけませんでしょうか? よろしくお願いします

    • ベストアンサー
    • Java
  • hashCode

    ObjectのhashCodeはどういう規則で生成されているのでしょうか? あるオブジェクトにおいて、オブジェクトの生成順番が実行毎に同じならばhashCodeは同一になるかと思っていたのですが、どうも違うようなので気になりました。 例えば、マルチスレッドでObjectの生成順序を毎回違うよう生成しても、ob配列ojbs1,objs2中の要素のhashCode()は同じになります。 public class HashCodeMultiThreadTest {  public static void main(String[] args) {   final Object[] objs1 = new Object[20];   final Object[] objs2 = new Object[20];   int one_or_two = (int) (Math.random()*2+1);   final long sleep_time1 = 100 * one_or_two;   final long sleep_time2 = 100 * (3-one_or_two);      Thread t1 = new Thread() {    public void run() { try{     for (int i=0; i<objs1.length; i++) {      objs1[i] = new Object();      Thread.sleep(sleep_time1);     }    }catch(Exception e){}}   };   Thread t2 = new Thread() {    public void run() { try {     for (int i=0; i<objs2.length; i++) {      objs2[i] = new Object();      Thread.sleep(sleep_time2);     }    }catch(Exception e){}}   };   try {    t1.start();    t2.start();    t1.join();    t2.join();   }catch(Exception e){}   for (Object o : objs2)    System.out.println(o.hashCode());  } }

    • ベストアンサー
    • Java
  • 交互にスレッド実行 (どうしてちゃんと動いてる?)

    http://oshiete1.goo.ne.jp/qa2968378.html で質問した者です。 2つのスレッドで1と2を交互に実行する以下のプログラム。 final Object obj1 = new Object(); //スレッド間通信用のobject final Object obj2 = new Object(); //スレッド間通信用のobject2 Thread t1 = new Thread() {  public void run() {   try {    while(true) {     System.out.print("1");     synchronized (obj1) {      synchronized (obj2) {       obj2.notify();//相手をnotifyして      }      obj1.wait();//自分はwait     }    }   } catech (Exception e){} }; Thread t2 = new Thread() {  public void run() {   try {    while(true) {     System.out.print("2");     synchronized (obj2) {      synchronized (obj1) {       obj1.notify();      }      obj2.wait();     }    }   } catch (Exception e){}  } }; Thread t1 = new Test1(); Thread t2 = new Test2(); t1.start(); while(t1.getState() != Thread.State.WAITING); t2.start(); が思ったように動いてはいるものの、なぜ正常に動いているかがわかりません。 t1が wait() したときはobj1のロックをもっていて、t2の synchronized (obj1){obj1.notify()} ブロックに入れず待機するはずだと思うのですが。 なぜちゃんと動いているのでしょう?

    • ベストアンサー
    • Java
  • C#のnew Thread以下のコード分解

    new Thread以下のコードを分解できますか? ====================== private void button1_Click(object sender,EventArgs e) { new Thread(new ThreadStart(delegate() { AllocConsole(); //開始============== for(uint i = 0;i < 100;++i) { Console.WriteLine("Hello " + i); } FreeConsole(); //終了============== })).Start(); } =================== 以上

  • (Visual C#)カスタムコントロールで作ったリストのプロパティを

    (Visual C#)カスタムコントロールで作ったリストのプロパティを.Items[i]で参照できるように したいです。 具体的に言うと、 Form1…フォームアプリケーション MyList…フォームコントロールライブラリ MyListItem…フォームコントロールライブラリ の3つのソリューションがあります。 Form1にはMyListをデザイナーで、 MyListにはFlowLayoutPanelがあり その中にMyListItemを入れるようにコードを組んであります。 MyList.sln - UserControl1.cs using 省略 namespace MyList { public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } public int Count = 0; public int SelectRow = -1; private MyListItem.MyListItem[] Mylistitem; private void Add (string URL, string Text, string ShowName, string Date){ Mylistitem[Count] = new MyListItem.MyListItem(); Mylistitem[Count].Text = Text + Count.ToString(); Mylistitem[Count].ImageURL = URL; Mylistitem[Count].ShowName = ShowName; Mylistitem[Count].Date = Date; Mylistitem[Count].Name = "MyListItem" + Count; Mylistitem[Count].Parent = this.flowLayoutPanel1; Mylistitem[Count].count = Count; this.Mylistitem[Count].Click += newEventHandler(this.MyListItem_Click); Count++; } private void button1_Click(object sender, EventArgs e) { Add("http://画像URL", "文字列1", "2", "3"); } private void UserControl1_Load(object sender, EventArgs e) { this.Mylistitem = new MyListItem.MyListItem[1000]; } } } MyListItem.sln - UserControl.csは省略します。 ここで質問なんですが、 Form1.csで、 private void TestMethod() { MyList1.Items[i].ImageURL = "http://画像URL"; } のようにしてMyList内のMyListItemのオブジェクト配列のなかで、 Count==iのものを探し、それのImageURLの値を変更することは可能でしょうか? 可能でしたら、その方法またはコードを教えていただけないでしょうか? 検索しても見つからなかったので質問しました。 回答よろしくお願いします。 あ、ちなみにVisual Studio 2010です。

  • 以下のコードのどこが問題なのでしょうか?

    java初心者です。よろしくお願いいたします。以下のコードはどこに問題があるのでしょうか?よろしくお願いいたします。 public class Sample2 { public static void main(String[] args1,String[] args2) { MyObject object = new MyObject(); object.setName("mikel" , "jun"); String s = object.getName(); System.out.println(s); } } class MyObject { String name; public void setName(String str1,String str2) { name = "str1"+"str2"; } public String getName() { return name; } }

    • ベストアンサー
    • Java
  • (ソースコード有)ArrayListについて

    (ソースコード有)ArrayListに何でも入れられるのが問題と本に書いてあったのですがどういうことですか? package jp.rutles.sample; import java.util.ArrayList; public class MyJavaApp { static ArrayList data; public static void main(String[] args) { data = new ArrayList(); data.add(new MyObject("Hello")); data.add(new MyObject("Welcome")); data.add(new MyObject("Bye!")); addString("etc"); for(Object obj : data){ MyObject myobj = (MyObject)obj; System.out.println(myobj); } } public static void addString(String s){ data.add(s); } } 本ではこれを実行すると、 プログラム自体は問題がなくコンパイルして実行できるのですが、途中でエラーが発生して強制終了します。 その原因がaddStringというメソッドがdataフィールドにStringオブジェクトを保管するものだからだそうです。 mainメソッドではMyObjectを追加して中身をそのままforで出力しているだけですが、取り出したオブジェクトをMyObjectにキャストするところで、エラーになってしまうらしいです。(なんかこの文の文法が少し変な気はしますが本もこのようにかいていますw) addStringを呼び出すと、ArrayListにStringが追加されます。このStringを取り出してMyObjectにキャストしようとしたためにエラーになってしまった。らしいです。 まず 「mainメソッドではMyObjectを追加して中身をそのままforで出力しているだけですが、 取り出したオブジェクトをMyObjectにキャストするところで、エラーになってしまう。」 というのがよくわかりません。 そして 「addStringを呼び出すと、ArrayListにStringが追加されます。このStringを取り出してMyObjectにキャストしようとしたためにエラーになってしまった。」 これもよくわかりません。 ArrayListになんでも入れれることがなぜ問題なのかを知りたいので この本ではこのあとこれを上手に解決する方法として ジェネリックスというものを解説してくれているのですが これは使わないようにお願いします! すごく注文が多いのですが どなたか教えてくださいお願いします!

    • ベストアンサー
    • Java

専門家に質問してみよう