user3157908:
私は、複数のスレッド間で共有整数オブジェクトを使用して順番に1から10までの数字を印刷しようとしています。AtomicIntegerとして共有オブジェクトを使用する場合、プログラムが正常に動作しますが、通常のIntegerオブジェクトを使用した場合、プログラムが例外をスローし、なぜこれが起こっている私にはわかりません。
AtomicIntegerとプログラム
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadingProblem {
public static void main(String[] args) {
AtomicInteger sharedInt = new AtomicInteger(0);
Thread t1 = new Thread(new ThreadingPrintingTask(sharedInt), "PrinterThread");
Thread t2 = new Thread(new ThreadingIncrementingTask(sharedInt), "IncrementerThread");
t1.start();
t2.start();
}
}
class ThreadingPrintingTask implements Runnable {
private AtomicInteger sharedObject;
public ThreadingPrintingTask(AtomicInteger sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
try {
synchronized (sharedObject) {
while (true) {
sharedObject.wait();
System.out.println("Shared object value is: " + sharedObject);
sharedObject.notify();
}
}
}
catch (InterruptedException e) {
}
}
}
class ThreadingIncrementingTask implements Runnable {
private AtomicInteger sharedObject;
public ThreadingIncrementingTask(AtomicInteger sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
synchronized (sharedObject) {
while (this.sharedObject.get() < 10) {
this.sharedObject.incrementAndGet();
this.sharedObject.notify();
try {
this.sharedObject.wait();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
出力
Shared object value is: 1
Shared object value is: 2
Shared object value is: 3
Shared object value is: 4
Shared object value is: 5
Shared object value is: 6
Shared object value is: 7
Shared object value is: 8
Shared object value is: 9
Shared object value is: 10
通常のIntegerオブジェクトを持つプログラム
public class ThreadingProblem {
public static void main(String[] args) {
Integer sharedInt = new Integer(0);
Thread t1 = new Thread(new ThreadingPrintingTask(sharedInt), "PrinterThread");
Thread t2 = new Thread(new ThreadingIncrementingTask(sharedInt), "IncrementerThread");
t1.start();
t2.start();
}
}
class ThreadingPrintingTask implements Runnable {
private Integer sharedObject;
public ThreadingPrintingTask(Integer sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
try {
synchronized (sharedObject) {
while (true) {
sharedObject.wait();
System.out.println("Shared object value is: " + sharedObject);
sharedObject.notify();
}
}
}
catch (InterruptedException e) {
}
}
}
class ThreadingIncrementingTask implements Runnable {
private Integer sharedObject;
public ThreadingIncrementingTask(Integer sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
synchronized (sharedObject) {
while (this.sharedObject < 10) {
this.sharedObject++;
this.sharedObject.notify();
try {
this.sharedObject.wait();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
出力
Exception in thread "IncrementerThread" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.itiviti.apps.catalys.shared.mock.ThreadingIncrementingTask.run(ThreadingProblem.java:52)
at java.lang.Thread.run(Unknown Source)
biziclop:
this.sharedObject++;
あなたはそれを行うだろうと仮定何をしません。
以来Integer
不変である、それは既存の共有オブジェクトを変更することはできません。何この操作ではなく、ないことにUnboxの値でありint
、それをインクリメントして、再び別のにそれをボックスInteger
のインスタンス。
あなたのコードは次のように(ほとんど*)と等価であるので:
int temp = this.sharedObject.intValue();
temp = temp + 1;
this.sharedObject = new Integer(temp);
この時点で、あなたのオブジェクトは、もはや同じインスタンスであるとして、あなたのsynchronized
ブロックはと整列しないだろうwait()
/のnotify()
呼び出し。
これはのアトミック性とは何の関係も持っていないことを注意はAtomicInteger
、それがどのように行うには、単純だ++
オペレータが上で動作しますInteger
。
*は、実際には、あなたの代わりにキャッシュされたインスタンスを取得する可能性がありますnew Integer()
が、それは別の表しとしてそれはまだ、別のインスタンスになりますint
値を。