prv*_*rvn 3 java multithreading volatile
我一直在经历JCIP,作者在那里说..
线程限制的特殊情况适用于volatile变量.只要确保volatile变量仅从单个线程写入,对共享的volatile变量执行读 - 修改 - 写操作是安全的.
例如,count ++被认为是一个复合操作(读取值,向其中添加一个值,并更新值)并将count指定为volatile不会使此操作成为原子操作,因此这里不保证线程安全!我对吗 ??但是这里作者说我们可以修复它,如果我们确保volatile变量只是从一个线程写的.我没理解这一点.请提供说明.
count ++本质上是两个操作,读取count和store count + 1的值.
如果两个线程同时尝试计数++,它们可能都会读取旧的count值并将其递增1.因此,最后,如果您不添加任何同步机制,最终将得到count + 1的最终值,而不是count + 2.
Volatile不保证在这种情况下(非原子)线程安全,它只保证最近存储的值可供所有线程使用.但这对上述情况没有多大帮助.您需要确保在存储新的线程之前,没有其他线程会读取旧的count值.
如果你需要有线程安全计数器,我建议你看一下AtomicInteger(和类似的)类.它们提供count ++的原子版本; incrementAndGet方法.
典型的用例可能如下所示:
public class Foo implements Runnable {
private volatile int itemsProcessed;
public int getItemsProcessed() { return itemsProcessed; }
@Override
public void run() {
while (true) { //this is just an example so we don't care about stopping
processItem(); //process a single item
itemsProcessed++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在其他人可以在没有额外同步的情况下查询线程的进度,但只允许线程本身更新它.对于其他人来说,该字段是只读的.
如果没有volatile其他线程可能根本看不到任何变化itemProcessed,或者甚至可能以古怪的顺序看到它们,有时会增加,有时会减少.
只有volatile写入是幂等的(即多次写入与单个写入具有相同的效果),多次线程可以在没有任何额外同步的情况下写入变量的唯一时间.这可以在用于停止线程的这种模式中看到:
public class Foo implements Runnable {
private volatile boolean stopped = false;
public void stopProcessing() {
stopped = true;
}
public int getItemsProcessed() { return itemsProcessed; }
@Override
public void run() {
while (!stopped) {
processItem(); //process a single item
}
}
}
Run Code Online (Sandbox Code Playgroud)
其他线程可以做的唯一事情是设置stopped为true.无论有多少人这样做,无论顺序如何,结果总是一样的.
| 归档时间: |
|
| 查看次数: |
475 次 |
| 最近记录: |