众所周知,简单的x++不是原子操作,而实际上是读-增量-写操作。这就是为什么它应该被同步。但是get()呢?我读过它也应该是同步的,但是有人能解释一下为什么吗?通过引入happens-before关系来避免内存一致性错误?如果get()经常被多个线程调用,而值很少更改,那该怎么办呢?synchronized get()不是在拖慢他们的脚步吗?在这种情况下(不使用AtomicInteger)有没有其他实现同步的方法?volatile关键字在这里可以工作吗?
public class Counter {
private int value;
public synchronized int get() { return value; }
public synchronized int increment() { return ++value; }
public synchronized int decrement() { return --value; }
}谢谢!
编辑:
我想说清楚。通过使用volatile,我的意思是在get()方法中引入该关键字并删除synchronized。我在想,如果有很多线程在读取值,而其中一个线程很少更改它,那么它是否会让它变得线程安全,而且效率也会更高。
发布于 2012-10-05 00:16:25
在这种情况下(不使用AtomicInteger),
有没有其他实现同步的方法?
首先,如果可以的话,你应该使用AtomicInteger。我不知道你为什么不用它。
关键字在这里会起作用吗?
是的,除了++。AtomicInteger在没有锁定的情况下提供安全的增量。如果你想滚动你自己的(出于某种疯狂的原因),那么你将需要阻塞,或者你需要复制AtomicInteger内部自旋机制。
但是
()怎么办呢?我读过它也应该是同步的,但是有人能解释一下为什么吗?
AtomicInteger包装了一个volatile int以提供其功能。当您访问volatile字段时,您也跨越了get()上的内存屏障。您需要跨越内存屏障,以确保如果另一个线程更新了该值,则调用get()的线程可以看到更新。否则,线程可能正在使用过时的值。
发布于 2012-10-05 00:19:20
如果您重复读取非易失性值,JVM可以在寄存器中缓存该值,您可能看不到任何更改。
避免这种情况的方法是将值设为易失性。
但是,如果性能是一个问题,请使用AtomicInteger,它是无锁的。
发布于 2012-10-05 00:21:20
但是
()怎么办呢?我读过它也应该是同步的,但是有人能解释一下为什么吗?
假设如果get()没有同步,那么当线程执行set()操作时,任何线程都可以调用它。
现在,假设线程B正在执行set()操作,将字段a的值设置为5。一个线程在set操作完成之前读取,另一个线程在set操作之后读取。
因此,这两个线程具有不同的值。因此,它们具有不一致的字段a状态。
现在假设get()方法是同步的..然后,如果线程正在设置一个值..则除非set()操作完成,否则任何线程都不能调用get()操作。因此,每个线程都将获得相同的值。
https://stackoverflow.com/questions/12731450
复制相似问题