Java 多对象和计数器的同步

Java 多对象和计数器的同步,java,synchronization,counter,synchronized,Java,Synchronization,Counter,Synchronized,我知道很多人在这个话题上有问题,你可能会觉得无聊,但我从几天开始就试图理解它,但仍然不知道它是如何工作的:(.我有一个计数器对象,还有另一个类的其他对象(将来不止一个类).现在每个对象都应该响应计数器执行。一个计数-每个对象运行方法的一个步骤。这是我的代码: public class Th { private final static Object lock1 = new Object(); ////////////////////////////////////////////////

我知道很多人在这个话题上有问题,你可能会觉得无聊,但我从几天开始就试图理解它,但仍然不知道它是如何工作的:(.我有一个计数器对象,还有另一个类的其他对象(将来不止一个类).现在每个对象都应该响应计数器执行。一个计数-每个对象运行方法的一个步骤。这是我的代码:

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();


   }

}
我需要的是:

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
...

计数器
线程的整个循环在
lock1
上同步。这意味着,尽管在此循环中调用
notifyAll
,但在整个循环在
计数器
线程中结束之前,其他线程无法重新获得锁

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

但请注意,这还不够,因为计数器线程可能在所有停止线程重新获取锁之前重新获取锁。您需要让计数器线程在另一个条件下等待,并在所有停止线程都显示计数后使其重新启动


您应该研究更高级别的抽象,如CyclicBarrier和CountDownLatch。

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

但是,如果您想以“艰难的方式”进行学习,您需要认识到这个问题需要计数器和停止线程等待特定的“事件”

  • 停止线程需要等待,直到计数器线程告诉它们前进到下一个停止

  • 计数器线程需要等待,直到所有停止线程都已前进并停止


当前实现的一个问题是,当所有停止线程都已前进并停止时,计数器线程无法告诉它。相反,它假定当它看到notify事件时,可以发出下一个计数。

我尝试了这个方法,但它没有解决问题(或者说解决了问题的一部分:)。这是一个输出:
0计数器0停止1计数器2计数器3计数器4计数器0停止2 1停止1 5计数器2停止1 6计数器7计数器8计数器9计数器10计数器11计数器12计数器13计数器14计数器1停止2 3停止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
...