0

複数のスレッドが共有オブジェクトのメソッドを呼び出して、そこに格納されているカウンターをインクリメント/デクリメント/印刷するコードを作成しようとしていました。また、これらの数値が0から8の間で変動することも必要です。つまり、出力は次のようになります。0123234567654566677877666655...。

誰かが私がクランクアウトしたものを見て、私が正しい軌道に乗っているかどうかについていくつかの指針を教えてもらえますか?

私の共有オブジェクト:

public class SyncObj{
        private int i;
        public synchronized void inc(){
                if(i<8)
                  i++;
        }
        public synchronized void dec(){
                if(i > 0)
                   i--;
        }
        public synchronized void print(){
                System.out.print(i);
        }
}

印刷の枯渇を防ぎ、すべてのinc / decが確実に印刷されるようにするために、hasPrintedというプライベート変数を使用して、クラスを次のように書き直すことができます。

public class SyncObj{
            private int i;
            //Changed Boolean to boolean as Keith Randall pointed out
            private boolean hasPrinted = false;
            public synchronized void inc(){
                    if(i<8 && hasPrinted){
                      i++;
                      hasPrinted = false;
                    }
            }
            public synchronized void dec(){
                    if(i > 0 && hasPrinted){
                       i--;
                       hasPrinted = false;
                    }
            }
            public synchronized void print(){
                    System.out.print(i);
                    hasPrinted = true;
            }
    }

誰かが上記のスニペットを調べて、落とし穴や落とし穴を確認できますか?

ありがとう

4

2 に答える 2

1

印刷にキューを使用することに慣れる必要があります。

public class SyncObj {
  private volatile int i;
  private BlockingQueue<Integer> q = new LinkedBlockingQueue<Integer>();
  public synchronized void inc() {
    if (i < 8) {
      i++;
      q.add(i);
    }
  }
  public synchronized void dec() {
    if (i > 0) {
      i--;
      q.add(i);
    }
  }
  public void print() {
    for (Integer i = q.poll(); i != null; i = q.poll()) {
      System.out.print(i);
    }
  }
  private static volatile boolean stop = false;
  public static void main(String[] args) throws InterruptedException {
    final SyncObj o = new SyncObj();

    new Thread(new Runnable() {
      @Override
      public void run() {
        while (!stop) {
          o.inc();
        }
      }
    }).start();

    new Thread(new Runnable() {
      @Override
      public void run() {
        while (!stop) {
          o.dec();
        }
      }
    }).start();

    new Thread(new Runnable() {
      @Override
      public void run() {
        while (!stop) {
          o.print();
        }
      }
    }).start();

    Thread.currentThread().sleep(1000);
    stop = true;
  }
}

私の出力は次のようになります。

1012345678765432101234567876543210123456787654321012345678765432101234567876543210123456787654321012345678

于 2012-04-06T18:08:20.473 に答える
1

Boolean-> boolean、プリミティブ型の代わりにオブジェクトを使用しても意味がありません。

最初のコードは問題ありません。2 番目のコードでは、飢餓を防止したり、すべての inc/dec が印刷されるようにしたりするという要件を解決できません。inc/dec で値自体を出力しないのはなぜですか?

于 2012-04-06T16:12:58.900 に答える