5

私はマルチスレッドに不慣れで、マルチスレッドについて読んでいるときに、次のことを行うためにこの派手なマルチスレッドコードを書くことを考えました。

私のカウンタークラスは以下の通りです。

class Counter {
  private int c = 0;

  public void increment() {
    System.out.println("increment value: "+c);
      c++;
  }

  public void decrement() {
      c--;
      System.out.println("decrement value: "+c);
  }

  public int value() {
      return c;
  }

}

このCounterオブジェクトは、2つのスレッド間で共有されます。スレッドが開始されたら、次のことを行う必要があります。Thread1がCounterオブジェクトのカウントを1インクリメントするまで、Thread2を待機させます。これが完了すると、Thread 1はthread2に通知し、Thread1はthread2が値を1デクリメントするのを待機し始めます。次にthread2が開始し、値を1デクリメントします。スレッド1に再度通知し、スレッド2はスレッド1の待機を開始します。このプロセスを数回繰り返します。

どうすればこれを達成できますか。よろしくお願いします。

私は次のことをしました。

public class ConcurrencyExample {

  private static Counter counter;
  private static DecrementCount t1;
  private static IncrementCount t2;

  public static void main(String[] args) {
    Counter counter = new Counter();
    Thread t1 = new Thread(new IncrementCount(counter));
    t1.start();

    Thread t2 = new Thread(new DecrementCount(counter));
    t2.start();

  }

}


public class DecrementCount implements Runnable {

  private static Counter counter;

  public DecrementCount(Counter counter) {
    this.counter = counter;
  }

  @Override
  public void run() {
    for (int i = 0; i < 1000; i++) {
      counter.decrement();     
      System.out.println("decreamented");
    }
  }

}


public class IncrementCount implements Runnable {

  private static Counter counter;

  public IncrementCount(Counter counter) {
    this.counter = counter;
  }

  @Override
  public void run() {
    for (int i = 0; i < 1000; i++) {
      counter.increment();
      System.out.println("Incremented");
    }

  }

}
4

4 に答える 4

3

チェックアウトSemaphore。スレッドごとに1つずつ、合計2つ必要incSemaphoreですdecSemaphore。でDecrementCount

for (int i = 0; i < 1000; i++) {
  decSemaphore.acquire();
  counter.decrement();     
  System.out.println("decreamented");
  incSemaphore.release();
}

IncrementCount対称的に実装します。の初期値はとである必要incSemaphore1あります。0decSemaphore

ところで、Counter同期も必要です(synchronizedキーワードとを参照AtomicInteger)。

于 2012-09-25T16:16:07.107 に答える
0

ブールフラグでConditionを使用します。

final Lock lock = new ReentrantLock();
final Condition incremented= lock.newCondition(); 
final Condition decremented= lock.newCondition(); 

カウンターを以下に変更します

説明 :

2つの条件を使用しました。1つはインクリメントされ、もう1つはデクリメントされます。ブールフラグに基づいて、1つの条件で待機する必要があるかどうかを確認します。

 class Counter {
private int c = 0;
boolean increment = false;

final Lock lock = new ReentrantLock();
final Condition incremented = lock.newCondition();
final Condition decremented = lock.newCondition();

public void increment() throws InterruptedException {
    Lock lock = this.lock;
    lock.lock();
    try {
        while(increment)
            decremented.await();
        increment = true;           
        c++;
        System.out.println("increment value: " + c);
        incremented.signal();
    } finally {
        lock.unlock();
    }

}

public void decrement() throws InterruptedException {

    Lock lock = this.lock;
    lock.lock();
    try {
        while (!increment)
            incremented.await();
        c--;
        System.out.println("decrement value: " + c);
        increment = false;
        decremented.signal();
    } finally {
        lock.unlock();
    }
}

public int value() {
    Lock lock = this.lock;
    lock.lock();
    try {
        return c;
    } finally {
        lock.unlock();
    }
}

}
于 2012-09-25T16:12:44.013 に答える
0

シンクロナイザーにより、スレッドは相互に待機できるようになります。CountDownLatchおよびSemaphoreを参照してください。

java.util.concurrent パッケージの Synchronizers セクションを参照してください。

于 2012-09-25T16:17:00.350 に答える
0

-まず、競合状態を回避するためにincrement()andキーワードをdecrement()使用する必要があります このブライアンのルールを参照してくださいsynchronized

When we write a variable which has just been read by another thread, or reading a variable which is just lately written by another thread, must be using Synchronization. And those atomic statements/Methods accessing the fields' data must be also synchronized.

-どのスレッドJVM Thread Schedulerが実行中状態に入るか、どれくらいそこにとどまるか、作業が完了した後にどこに行くかを制御します。

-どのスレッドが最初Cannot be sureに実行されるか.....

-SingleThreadExecutor fromを使用することもできますjava.util.concurrent。これにより、2 つ目のタスクに移る前に 1 つのタスクが完了します。

于 2012-09-25T16:24:12.723 に答える