繁体   English   中英

类内部线程安全

[英]Class internal thread-safety

我正在用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等)的内容来看,它们本质上是线程安全的。

编辑:向字段添加默认值

我的问题是,这个类内部是线程安全的吗? 从我读到的有关不可变对象(如Byte等)的内容来看,它们本质上是线程安全的。

我在您的课程中看到的线程安全问题是您正在更新两个看起来相关的字段。 由于竞争条件,有可能看到新的channel值和旧的mode值。 我会使用一个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 ,那么您的类应该是线程安全的,因为值将以原子方式更新并且内存正确同步。

如果更改内部字段,则类不是不可变的。 不可变类不会改变。 这意味着您的类不是线程安全的。

这是真的,如果你没有公开任何setter或任何其他改变你的类的方法它应该是不可变的,但在这种情况下你在内部更改它。 固有的线程安全意味着它不能改变,所以你不必担心不同的线程会竞争和破坏彼此的数据。 这肯定不是这种情况。

你的班级不是线程安全的。 原因:如果//get new data[]...是一个耗时的步骤,那么其他方法可能会尝试在内部字段初始化之前读取内部字段。 构造函数中的内部线程不会停止对象构造和初始化,因此在准备数据之前它可能具有不一致的状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM