0

次のプログラムを実行しようとすると、次のコードの notify () への最初の呼び出しで IllegalMonitorStateException が発生します。

synchronized (c) {
    try {
        notify();
        ....

これは私を少し混乱させます: 同じロックをチェックする同期ブロックに既にある場合、コードがオブジェクト (c) にロックを持たないのはどうしてですか?

notify() と wait() の乱用がやや奇妙に見えることは気にしないでください。同じタスクを実行するさまざまな (そしてより効率的な) 実装があることは知っていますが、現在、この特定の実装が機能しない理由を突き止めようとしています。

完全なコードは次のとおりです。

  class J implements Runnable {

        public static void main(String[] x) {
            Calc calc = new Calc();
            J j = new J(calc);
            Thread t1 = new Thread(j, "one");
            Thread tCalc = new Thread(calc, "Calc");
            tCalc.start();
            t1.start();
        }
        Calc c;
        public J(Calc c) {
            this.c = c;
        }

        public void run() {
            synchronized (c) {
                try {
                    notify();
                    c.wait();
                } catch (InterruptedException e) {

                }
                System.out.println(Thread.currentThread().getName() + ": x = "
                        + c.getX());
                notify();
            }
        }
    }

    class Calc implements Runnable {

        private int x;

        public int getX() {
            return x;
        }

        public void run() {
            synchronized (this) {

                for (int x = 1; x <= 11111; x *= (x + x)) {
                    this.x += x;
                    try {
                        notify();
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                notify();
            }
        }
    }
4

3 に答える 3

3

現在保持していない別のロックを待機しているスレッドに通知しようとしています。エラーは正当化されます。オブジェクト c をロックしてから、現在のオブジェクトのロックについて他のスレッドに通知します。

于 2012-08-02T14:18:49.903 に答える
1
synchronized (c) {
    try {
        notify();
        ....

オブジェクトをロックしていますが、オブジェクトcに通知していますthiswait()将来、現在のオブジェクトまたは現在のオブジェクトを常にnotify()明示的に指定することをお勧めします。やったほうがいい:

synchronized (c) {
    try {
        c.notify();
        ....

また:

synchronized (this) {
    try {
        this.notify();
        ....

あなたは実際に2つのロックを扱っているようです。この場合、次のようなことを行います。

synchronized (c) {
    try {
        synchronized (this) {
            this.notify();
        }
        c.wait();

c常に最初にロックしていることを確認することが重要ですthis。そうしないと、デッドロックが発生します。

于 2012-08-02T14:20:26.913 に答える
0

あなたが持っているのは、次のことを行う複雑な方法です。

ExecutorService printer = Executors.newSingleThreadExecutor();

int x2 = 0;
for (int x = 1; x <= 11111; x *= (x + x)) {
    x2 += x;
    final int x3 = x2;
    printer.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ": x = " + x3);
        }
    });
}
printer.shutdown();

これは、2 つのスレッドを使用して 1 つのスレッドを使用する方が高速で簡単な処理を実行しようとしていない場合は、さらに簡単になります。

于 2012-08-02T14:50:35.353 に答える