【发布时间】:2015-06-30 18:55:34
【问题描述】:
如果我有一个字节队列,预计会有一个线程生产者,另一个消费者:
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; }
// ...
}
这种类型的队列不需要同步。
readIdx 仅由阅读器线程修改,
writeIdx 仅由编写器线程编写。
readIdx == writeIdx 表示,没有内容。
并且队列最多只能占用 buf.length-1 字节的数据。
是否需要 volatile 或者是否可以省略它们,因为只有一个线程是一个整数状态的修饰符?
谢谢 弗兰克
【问题讨论】:
-
您需要更强大的同步,
writeIdx更新必须始终发生在buf更新之后。没有synchronized会很棘手。 -
同意班塔尔。谨慎行事,不要走捷径。写入正确的同步。不要为了获得一纳秒而牺牲正确性。
-
您对修改的看法是对的,但不要忘记读取也在发生。
-
当任何其他线程正在使用
read()或write()方法时,是否可以调用available()?如果是这样,那它应该是什么意思? (提示:你能做的最好的就是返回在某个时刻是可用的字节数,但这不一定与是 在调用者决定做某事时可用。)
标签: java multithreading volatile memory-visibility