许多对象和计数器的同步

时间:2012-01-15 10:11:42

标签: java synchronization counter synchronized

我知道很多人都有这个话题的问题,你可能会感到无聊,但我试着理解它,因为几天仍然不知道它是如何工作的:(。我有一个计数器对象和其他对象另一个类(将来多于一个类)。现在每个对象都应该响应计数器执行。一个计数 - 每个对象运行方法的一步。这是我的代码:

public class Th {

  private final static Object lock1 = new Object();

////////////////////////////////////////////////////////////////////////////////

  private class Stop implements Runnable {

    private int count, id;

    public Stop(int id) {
      this.count = 0;
      this.id = id;
    }

    @Override public void run() {
      synchronized(lock1){
        while (count < 20) {
          try {
            lock1.wait();
          } 
          catch (InterruptedException exception) {
                System.out.println("Error!");
          }
          System.out.println(count + " stop " + id);
          this.count++;

//          try {
//            Thread.sleep(360);
//          }
//          catch (InterruptedException exception) {
//            System.out.println("Error!");
//          } 

        }
      }
    }

  } 

////////////////////////////////////////////////////////////////////////////////

  private class Counter implements Runnable {

    private int count;

    public Counter() {
      this.count = 0;
    }

    @Override public void run() {

      synchronized(lock1){
        while (count<15) {
          lock1.notifyAll();

          System.out.println(count + " counter");
          this.count++;      

//          try {
//            Thread.sleep(360);
//          }
//          catch (InterruptedException exception) {
//            System.out.println("Error!");
//          }          

        }
      }
    }

  } 

   public void test() {

     Stop s1 = new Stop(1);
     Stop s2 = new Stop(2);
     Stop s3 = new Stop(3);

     Counter counter = new Counter();

     (new Thread(s1)).start();
     (new Thread(s2)).start();
     (new Thread(counter)).start();
     (new Thread(s3)).start();


   }

}

它返回了类似的内容:

run:
0 counter
1 counter
2 counter
3 counter
4 counter
5 counter
6 counter
7 counter
8 counter
9 counter
10 counter
11 counter
12 counter
13 counter
14 counter
0 stop 1

我需要的是:

0 counter
0 stop 0
0 stop 1
0 stop 2
1 counter
1 stop 0
1 stop 1
1 stop 2
2 counter
2 stop 0
2 stop 1
2 stop 2
3 counter
...

2 个答案:

答案 0 :(得分:4)

Counter线程的整个循环在lock1上同步。这意味着虽然在此循环中调用notifyAll,但在Counter线程中完成循环结束之前,其他线程无法重新获取锁。

使循环的每次迭代同步,而不是在循环外同步。

请注意,这是不够的,因为Counter线程可能会在所有Stop线程重新获取之前重新获取锁。您需要让Counter线程在另一个条件下等待,并在所有Stop线程显示计数时重新启动它。

您应该调查更高级别的抽象,例如CyclicBarrier和CountDownLatch。

答案 1 :(得分:3)

首先,解决此问题的最佳方法是使用更高级别的同步类,如JB Nizet所说。

但是如果你想“艰难地”做一个学习练习,你需要认识到这个问题需要Counter和Stop线程等待特定的“事件”。

  • Stop线程需要等到Counter线程告诉他们前进到下一站。

  • 计数器线程需要等到所有停止线程已提前并停止。

当前实现的一个问题是,当所有Stop线程都已提前并停止时,Counter线程无需告诉它。相反,它假设当它看到一个通知事件时,可以发出下一个计数。