3

Java で内部的にマルチスレッド化されたクラスを作成しています。これは、別のスレッドを初期化して使用してプライベート フィールドを更新するという点です。

class Foo {
    private volatile Byte channel = new Byte(0);
    private volatile Byte mode = new Byte(0);

    public Foo() {
        Thread t = new Thread(new UpdateFields());
        t.setDaemon(true);
        t.start();
    }

    public Byte getChannel() {
        return this.channel;
    }  

    public Byte getMode() {
        return this.mode;
    }

    private class UpdateFields implements Runnable {
        @Override public void run() {
            Byte data[];
            //get new data[]...
            channel = data[0];
            mode = data[1];
        }
    } 
}

私の質問は、このクラスは内部的にスレッドセーフですか? Byte などの不変オブジェクトに関して私が読んだことから、それらは本質的にスレッドセーフであるということです。

編集:フィールドにデフォルト値を追加

4

3 に答える 3

7

私の質問は、このクラスは内部的にスレッドセーフですか? Byte などの不変オブジェクトに関して私が読んだことから、それらは本質的にスレッドセーフであるということです。

あなたのクラスで見られるスレッド セーフの問題は、関連しているように見える 2 つのフィールドを更新していることです。channel競合状態のために、新しい値と古い値が表示される可能性がありmodeます。2 つのフィールドvolatile ChannelModeの代わりにオブジェクトを使用します。volatile

public class ChannelMode {
    private byte channel;
    private byte mode;
    public byte getChannel() {
       return channel;
    }
    public byte getMode() {
       return mode;
    }
}

必須ではありませんが、直接Atomic*ではなくクラスを使用しvolatileたいので、AtomicReference<ChannelMode>. したがって、コードは次のようになります。

private AtomicReference<ChannelMode> channelModeRef =
    new AtomicReference<ChannelMode>(
        new ChannelMode(INITIAL_CHANNEL, INITIAL_MODE));
...
Byte data[];
// get new data[]...
// atomic operation to set the new channel-mode
channelModeRef.set(new ChannelMode(data[0], data[1]);

内部スレッドが頻繁に更新する場合ChannelMode、値がアトミックに更新され、メモリが適切に同期されるという点で、クラスはスレッドセーフである必要があります。

于 2013-09-19T15:10:30.720 に答える
1

あなたのクラスはスレッドセーフではありません。理由://get new data[]...時間がかかるステップの場合、内部スレッドによって初期化される前に、他のメソッドが内部フィールドを読み取ろうとする可能性があります。コンストラクターの内部スレッドはオブジェクトの構築と初期化を停止しないため、データが準備されるまで、一貫性のない状態になる可能性があります。

于 2013-09-19T15:18:21.967 に答える
1

内部フィールドを変更すると、クラスは不変ではなくなります。不変クラスは変更されません。これは、クラスがスレッドセーフではないことを意味します。

クラスを変更するセッターやその他のメソッドを公開しない場合は不変であるはずですが、この場合は内部的に変更します。本質的にスレッドセーフとは、変更できないことを意味するため、異なるスレッドが競合して互いのデータが破損することを恐れる必要はありません。これは確かにここでは当てはまりません。

于 2013-09-19T15:06:50.377 に答える