使用volatile确保Java中共享(但不是并发)数据的可见性
我正在尝试实现LZ77的快速版本,我有一个关于并发编程的问题要问你 现在我有一个使用volatile确保Java中共享(但不是并发)数据的可见性,java,multithreading,concurrency,volatile,memory-visibility,Java,Multithreading,Concurrency,Volatile,Memory Visibility,我正在尝试实现LZ77的快速版本,我有一个关于并发编程的问题要问你 现在我有一个final byte[]buffer和一个final int[]resultHolder,两者的长度相同。该程序执行以下操作: 主线程写入所有缓冲区,然后通知线程并等待它们完成 单个工作线程处理缓冲区的一部分,将结果保存在结果保持器的相同部分中。工人部分是专用的。在此之后,主线程被通知,工作线程暂停 当所有工作线程都暂停时,主线程读取resultHolder中的数据并更新缓冲区,然后(如果需要)流程从第1点再次开始
final byte[]buffer
和一个final int[]resultHolder
,两者的长度相同。该程序执行以下操作:
final byte[] buffer = new byte[SIZE];
final MemoryHelper memoryHelper = new MemoryHelper();
final ArrayBlockingQueue<Object> waitBuffer = new ArrayBlockingQueue<Object>(TOT_WORKERS);
final ArrayBlockingQueue<Object> waitResult = new ArrayBlockingQueue<Object>(TOT_WORKERS);
final int[] resultHolder = new int[SIZE];
final byte[]buffer=新字节[SIZE];
final MemoryHelper MemoryHelper=新的MemoryHelper();
最终ArrayBlockingQueue waitBuffer=新ArrayBlockingQueue(TOT_工人);
最终ArrayBlockingQueue waitResult=新ArrayBlockingQueue(TOT_工人);
最终整数[]结果文件夹=新整数[大小];
MemoryHelper简单地包装了一个volatile字段,并提供了两种方法:一种用于读取它,另一种用于写入它
辅助进程的run()代码:
public void run(){
试一试{
//等待主线程
while(manager.waitBuffer.take()!=关机){
//加载新的缓冲区值
manager.memoryHelper.readVolatile();
//做点什么
对于(int i=a;i您甚至不需要这里的volatile
,因为已经提供了必要的内存可见性保证:
内存一致性影响:与其他并发集合一样,在将对象放入另一个线程中的BlockingQueue
之前线程中的操作,在另一个线程中从BlockingQueue
访问或移除该元素之后的操作
一般来说,如果您已经有了某种类型的同步,您可能不需要做任何特殊的事情来确保内存的可见性,因为您使用的同步原语已经保证了这一点
但是,当您没有显式同步时(例如,在无锁算法中),可以使用
volatile读写来确保内存可见性
p.S.
另外,您似乎可以使用它来代替队列解决方案,它是专为类似场景设计的。+1同意。添加了到JLS 17.4.5的链接,该链接描述了与CyclicBarrier尝试的“之前发生”关系,代码更简洁。谢谢!另请参阅
public void run() {
try {
// Wait main thread
while(manager.waitBuffer.take() != SHUTDOWN){
// Load new buffer values
manager.memoryHelper.readVolatile();
// Do something
for (int i = a; i <= b; i++){
manager.resultHolder[i] = manager.buffer[i] + 10;
}
// Flush new values of resultHolder
manager.memoryHelper.writeVolatile();
// Signal job done
manager.waitResult.add(Object.class);
}
} catch (InterruptedException e) { }
}
for(int i=0; i < 100_000; i++){
// Start workers
for (int j = 0; j < TOT_WORKERS; j++)
waitBuffer.add(Object.class);
// Wait workers
for (int j = 0; j < TOT_WORKERS; j++)
waitResult.take();
// Load results
memoryHelper.readVolatile();
// Do something
processResult();
setBuffer();
// Store buffer
memoryHelper.writeVolatile();
}