She*_*ard 3 java concurrency multithreading volatile memory-visibility
我正在尝试实现LZ77的快速版本,我有一个问题要问你关于并发编程的问题.
现在我有一个final byte[] buffer和final int[] resultHolder两个相同的长度.该计划执行以下操作:
主线程写入所有缓冲区,然后通知线程并等待它们完成.
单个工作线程处理缓冲区的一部分,将结果保存在结果持有者的同一部分中.工人的部分是独家的.之后,通知主线程并且工作人员暂停.
当所有工作者都暂停时,主线程读取resultHolder中的数据并更新缓冲区,然后(如果需要)该过程再次从第1点开始.
manager(主线程)中的重要事项声明如下:
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];
Run Code Online (Sandbox Code Playgroud)
MemoryHelper只是包装一个volatile字段并提供两种方法:一种用于读取它,另一种用于写入它.
Worker的run()代码:
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) { }
}
Run Code Online (Sandbox Code Playgroud)
最后,主线程的重要部分:
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();
}
Run Code Online (Sandbox Code Playgroud)
ArrayBlockingQueue上的同步效果很好.我的疑问是使用readVolatile()和writeVolatile().我被告知写入一个volatile字段会刷新所有以前更改的数据,然后从另一个线程读取它会使它们可见.
那么在这种情况下是否足以确保正确的可见性?从来没有真正的并发访问相同的内存区域,因此volatile字段应该比ReadWriteLock便宜很多.
你甚至不需要volatile这里,因为BlockingQueues已经提供了必要的内存可见性保证:
内存一致性效果:与其他并发集合一样,在将对象置于从另一个线程中访问或删除该元素之后的
BlockingQueue发生之前的操作之前BlockingQueue,线程中的操作.
通常,如果您已经进行了某种同步,则可能不需要执行任何特殊操作来确保内存可见性,因为它已经由您使用的同步原语保证.
但是,volatile当您没有显式同步时(例如,在无锁算法中),可以使用读取和写入来确保内存可见性.
PS
此外,您似乎可以使用CyclicBarrier队列代替您的解决方案,它专门针对类似场景而设计.
| 归档时间: |
|
| 查看次数: |
275 次 |
| 最近记录: |