1. 内存模型与CPU缓存

为了解决这个问题，有两种方式：

# 2. 并发环境下的可见性、原子性、有序性

JAVA原子性适用于除了long和double的原始数据类型的“简单操作”。从内存中读写除了long和double的原始数据类型是原子操作的。

i++            # java中不是原子的
i = i+1        # java中不是原子的
i = j          # java中不是原子的
i = 1          # java中是原子的

Java中原子性保证：Java内存模型只保证了基本读取和赋值是原子性操作，如果要实现更大范围操作的原子性，可以通过synchronized和Lock来实现。由于synchronized和Lock能够保证任一时刻只有一个线程执行该代码块，那么自然就不存在原子性问题了，从而保证了原子性。

Java中可见性保证：synchronized和Lock、volatile三种。推荐synchronized方式，volatile有局限性，适合某个特定场合。

# 3. Java的volatile关键字

volatile 单词的意思：易变的，不稳定的，易挥发的。

volatile 含义：

The volatile keyword also ensures visibility across the application. If you declare a field to be volatile, this means that as soon as a write occurs for that field, all reads will see the change. This is true even if local caches are involved—volatile fields are immediately written through to main memory, and reads occur from main memory.

It’s important to understand that atomicity and volatility are distinct concepts. An atomic operation on a non-volatile field will not necessarily be flushed to main memory, and so another task that reads that field will not necessarily see the new value. If multiple tasks are accessing a field, that field should be volatile; otherwise, the field should only be accessed via synchronization. Synchronization also causes flushing to main memory, so if a field is completely guarded by synchronized methods or blocks, it is not necessary to make it volatile.

volatile关键字的局限：
volatile doesn’t work when the value of a field depends on its previous value (such as incrementing a counter), nor does it work onfields whose values are constrained by the values of other fields, such as the lower and upper bound of a Range class which must obey the constraint lower <= upper.
It’s typically only safe to use volatile instead of synchronized if the class has only one mutable field. Again, your first choice should be to use the synchronized keyword—that’s the safest approach, and trying to do anything else is risky.

If you define a variable as volatile, it tells the compiler not to do any optimizations that would remove reads and writes that keep the field in exact synchronization with the local data in the threads. In effect, reads and writes go directly to memory, and are not cached, volatile also restricts compiler reordering of accesses during optimization. However, volatile doesn’t affect the fact that an increment isn’t an atomic operation.

Basically, you should make a field volatile if that field could be simultaneously accessed by multiple tasks, and at least one of those accesses is a write. For example, a field that is used as a flag to stop a task must be declared volatile.

http://www.cnblogs.com/dolphin0520/p/3920373.html

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120