在 Java 中,如果变量的大小小于或等于 32 位,则赋值是原子的,但如果大于 32 位则不是。
在双重或长期分配的情况下,使用什么(易失性/同步)更有效?
像,
volatile double x = y;
同步不适用于原始参数。在这种情况下如何使用同步?当然我不想锁定我的班级,所以this
不应该使用。
在 Java 中,如果变量的大小小于或等于 32 位,则赋值是原子的,但如果大于 32 位则不是。
在双重或长期分配的情况下,使用什么(易失性/同步)更有效?
像,
volatile double x = y;
同步不适用于原始参数。在这种情况下如何使用同步?当然我不想锁定我的班级,所以this
不应该使用。
你想做什么?synchronized
和关键字是 Java 中的volatile
机制,可用于确保读取相同数据的不同线程观察到一致的值。特别是,它们允许您推理程序中的发生之前的关系。
您根本无法避免使用volatile
orsynchronized
之一来正确访问final
多线程程序中的非字段。也就是说,您可能需要synchronized
over的主要原因是需要volatile
使用原子比较和设置操作(即,它不会考虑任何性能)。例如,在多线程程序中:
volatile int i = 0;
public void foo() {
if (i == 0) i = i + 1;
}
上面的代码本质上是不安全的,即使变量的声明为 volatile 意味着读取和写入被刷新到主内存 - 这种方法的唯一安全实现是这样的:
int i = 0;
public synchronized void foo() {
if (i == 0) i = i + 1;
}
那么你应该更喜欢哪个?好吧,如果您有多个线程根据该字段的值修改一个字段(即比较和设置),那么synchronized
这是唯一安全的解决方案。
还值得一提的是:的性能开销synchronized
不是问题(在绝大多数情况下)。同步性能问题通常是由于不必要的代码瓶颈、死锁或活锁造成的,必要时可以缓解。任何纯时钟周期开销都将与应用程序所做的其他事情相形见绌:文件 IO、数据库查询、远程处理等。
如果您发现对对象本身的锁定过于繁重,那么同步就是要走的路。在 Java 1.5 之前, volatile 可能是一个不错的选择,但现在 volatile 可以通过强制对发生赋值的方法进行指令排序来产生非常大的影响。创建一个单独的对象 ( private final Object X_LOCK = new Object();
) 并在设置或获取该双精度值时对其进行同步。这将为您提供对锁定的精细控制,这似乎是您需要的。
在新的并发包中有更多选项,例如 AtomicReference 如果您确实需要避免同步,它可能是 volatile 的一个很好的替代品。
如果你只是做一个任务, volatile 肯定是要走的路。我相信你知道,但是自从它被提出:如果你想做更复杂的操作(例如增加值),你需要同步。i++ 对于任何类型的变量都不是线程安全的。你需要同步。i++ 之类的,因为这实际上不止 1 次操作。
不是:有人表示可以使用 AtomicDouble,但 java.util.concurrent.atomic 中目前没有 AtomicDouble
如果您在 x 上执行多项操作,这需要在最后将其设置为新值,则可以以线程安全的方式执行此操作,而无需任何锁定,并使其成为线程安全的,使用 compare 和放。例子:
AtomicLong x = new AtomicLong(SomeValue);
public void doStuff() {
double oldX;
double newX;
do {
oldX = x.get();
newX = calculateNewX(oldX);
} while (!x.compareAndSet
(Double.doubleToLongBits(oldX), Double.doubleToLongBits(newX)));
This works because compareAndSet will see if the value of x has changed since the last time you read it. If x has changed then you are forced to do the computation over again and re-try setting it.
You could of course implement your own AtomicDouble instead of doing these doubleToLongBits conversions. Take a look at AtomicFieldUpdater.
KDSRathore,您可以使用一些显式锁,或制作一些虚拟 Object object = new Object() ,您可以在该双精度的 setter/getter 中同步
According to the oracle documentation, you can use volatile to refer to Double object:
volatile Double x = y;
"Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values."