简体   繁体   English

需要挥发性吗?

[英]Is volatile needed?

if I have a byte queue, where it is expected to have one thread producer, another consumer: 如果我有一个字节队列,它应该有一个线程生成器,另一个消费者:

class ByteQueue{
    byte[] buf;
    /*volatile?*/ int readIdx;
    /*volatile?*/ int writeIdx;
    Runnable writeListener;
    Runnable readListener;
    // ...
    void write( byte[] b ){
        int wr = writeIdx;
        int rd = readIdx;
        // check consistency and free space using wr+rd
        // copy to buf, starting at wr, eventually wrap around
        // update writeIdx afterwards
        writeIdx = ( wr + b.length ) % buf.length;
        // callback to notify consumer for data available
        writeListener.run();
    }
    void read( byte[] b ){
        int wr = writeIdx;
        int rd = readIdx;
        // check consistency and available data using wr+rd
        // copy buf to b, starting at rd, eventually wrap around
        // update readIdx afterwards
        readIdx = ( rd + b.length ) % buf.length;
        // callback to notify producer for free space available
        readListener.run();
    }
    int available() { return (writeIdx - readIdx) % buf.length; }
    int free() { return buf.length - available() -1; }
    // ...
}

This type of queue should not need synchronization. 这种类型的队列不需要同步。
readIdx is only modified by reader thread, readIdx仅由读者线程修改,
writeIdx only by the writer thread. writeIdx只由作者线程组成。

readIdx == writeIdx means, there is no content. readIdx == writeIdx意味着,没有内容。
And the queue can only take up to buf.length-1 bytes of data. 并且队列只能占用buf.length-1字节的数据。

Are the volatiles needed or can they be omitted because only one thread is the modifier of one integer state? 是否需要挥发物或者是否可以省略它们,因为只有一个线程是一个整数状态的修饰符?

thx Frank 弗兰克

If another thread has to read it, it needs to be volatile. 如果另一个线程必须读取它,它需要是易失性的。 The volatile keyword indicates to the JVM that the value can't be cached or have its updates reordered, otherwise updates to its value may not be visible to other threads. volatile关键字向JVM指示无法缓存该值或重新排序其更新,否则其值的更新可能对其他线程不可见。

The visibility concern extends to the buf array too. 可见性问题也延伸到buf阵列。 Since buf needs to change in step with the indexes it would seem like the write and read methods need to be synchronized. 由于buf需要随索引一步改变,因此看起来需要同步write和read方法。 Synchronization makes the changes visible and makes sure that concurrent calls don't result in the indexes and buf contents becoming inconsistent. 同步使更改可见,并确保并发调用不会导致索引和buf内容变得不一致。

You should declare them volatile . 你应该声明它们是volatile Let's look, for example, at readIdx . 让我们看看,例如,在readIdx If it it not volatile , writer thread optimization can assume it is never changed and make wrong optimizations based on that assumption. 如果它不是volatile ,则编写器线程优化可以假设它永远不会被更改并基于该假设进行错误的优化。

However, I don't see that you access readIdx anywhere in writer thread (or writeIdx in reader thread) apart for assignment to some local variable rd (or wr ). 但是,我没有看到您在writeIdx器线程(或读取器线程中的readIdx任何位置访问readIdx ,除了分配给某个局部变量rd (或wr )。 I just assume there is some code missing or otherwise your question doesn't really make sense. 我只是假设有一些代码缺失或者你的问题没有意义。

Nathan is correct, it's not that the two threads would write over each others variables, but that the variables themselves would risk to never be visible for the other thread (or rather CPU-core). Nathan是正确的,并不是两个线程会在每个其他线程上写入变量,而是变量本身存在永远不会对另一个线程(或者更确切地说是CPU核心) 可见的风险。

There is an interesting queue that actually uses non-volatile variables to let the CPU better schedule the work, the LMAX disruptor . 有一个有趣的队列实际上使用非易失性变量让CPU更好地安排工作,即LMAX干扰器

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

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