这是OpenJDK6的hotspot/src/share/vm/prims/unsafe.cpp代码片段(从第1082行开始):
// JSR166 ------------------------------------------------------------------
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
UnsafeWrapper("Unsafe_CompareAndSwapObject");
oop x = JNIHandles::resolve(x_h);
oop e = JNIHandles::resolve(e_h);
oop p = JNIHandles::resolve(obj);
HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
if (UseCompressedOops) {
update_barrier_set_pre((narrowOop*)addr, e);
} else {
update_barrier_set_pre((oop*)addr, e);
}
oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e);
jboolean success = (res == e);
if (success)
update_barrier_set((void*)addr, x);
return success;
UNSAFE_END
Run Code Online (Sandbox Code Playgroud)
还添加了关键方法oopDesc :: atomic_compare_exchange_oop.
inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value,
volatile HeapWord …Run Code Online (Sandbox Code Playgroud) 我正在实现一个简单的缓存,缓存存储为AtomicReference.
private AtomicReference<Map<String, String>> cacheData;
Run Code Online (Sandbox Code Playgroud)
应该从数据库表中填充(延迟)缓存对象.
我提供了一种方法来将缓存数据返回给调用者,但如果数据为空(即未加载),则代码需要从数据库加载数据.为避免同步我想到使用compareAndSet()方法:
public Object getCacheData() {
cacheData.compareAndSet(null, getDataFromDatabase()); // atomic reload only if data not set!
return Collections.unmodifiableMap(cacheData.get());
}
Run Code Online (Sandbox Code Playgroud)
以这种方式使用compareAndSet是否可以.将数据库调用作为原子动作的一部分?是否比同步方法更好/更差?
非常感谢任何建议..
我想知道在调用之间是否存在任何差异(或可能的副作用):
AtomicBoolean.set(true)
Run Code Online (Sandbox Code Playgroud)
和
AtomicBoolean.compareAndset(false, true)
Run Code Online (Sandbox Code Playgroud)
JavaDoc AtomicBoolean#set状态:
无条件地设置为给定值.
虽然AtomicBoolean#compareAndSet状态:
如果当前值==期望值,则以原子方式将值设置为给定的更新值.
在这两种情况下,该值都将设置为true.那么区别是什么呢?
正如安东尼·威廉斯说:
some_atomic.load(std :: memory_order_acquire)只是简单地加载到一个简单的加载指令,some_atomic.store(std :: memory_order_release)直接转到一个简单的存储指令.
众所周知,在x86上,操作load()和store()内存屏障memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel不需要处理器指令.
但在ARMv8我们知道,这里都是内存壁垒load()和store():
http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of- 2
http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2
关于CPU的不同架构:http://g.oswego.edu/dl/jmm/cookbook.html
接下来,但对于x86上的CAS操作,具有不同内存屏障的这两行在反汇编代码(MSVS2012 x86_64)中是相同的:
a.compare_exchange_weak(temp, 4, std::memory_order_seq_cst, std::memory_order_seq_cst);
000000013FE71A2D mov ebx,dword ptr [temp]
000000013FE71A31 mov eax,ebx
000000013FE71A33 mov ecx,4
000000013FE71A38 lock cmpxchg dword ptr [temp],ecx
a.compare_exchange_weak(temp, 5, std::memory_order_relaxed, std::memory_order_relaxed);
000000013FE71A4D mov ecx,5
000000013FE71A52 mov eax,ebx
000000013FE71A54 lock cmpxchg dword ptr [temp],ecx
Run Code Online (Sandbox Code Playgroud)
由GCC 4.8.1 …
在过去的几天里,我读了一些有关无锁编程的知识,我遍历了util.java.Random该类,并使用以下例程创建了它:
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
Run Code Online (Sandbox Code Playgroud)
根据这个 SO答案:
所谓的无锁算法倾向于对CAS指令使用严格的忙等待,但是在通常情况下竞争很低,以至于CPU通常只需要迭代几次。
和维基百科:
研究人员发现,在CAS处理失败后,无需立即重试,而是可以提高多处理器系统的整体系统性能,在多处理器系统中,如果看到CAS失败的线程使用指数退避,则许多线程会不断更新某些特定的共享变量,换句话说,请等待重试CAS之前需要一点时间。[4]
维基百科文章是否可以理解,已经找到但尚未使用,或者CAS指令在失败后人为地退缩是常见的做法。这是因为这样的循环对于cpu的使用不被认为是危险的,还是因为CAS一直没有引起争议?
第二个问题:是否有seed创建引用的特定原因,还是我们也可以简单地使用类作用域中的变量?
我正在阅读英特尔手册,卷。2A。
将 AL、AX、EAX 或 RAX 寄存器中的值与第一个操作数(目标操作数)进行比较。如果两个值相等,则将第二个操作数(源操作数)加载到目标操作数中。否则,目标操作数将加载到 AL、AX、EAX 或 RAX 寄存器中。RAX 寄存器仅在 64 位模式下可用。
如果失败,将目的地加载到累加器中的目的是什么?
a = b如果条件c成立,我需要自动分配,如果条件不成立,则不分配.有没有办法在C/C++中做到这一点?
澄清:我的意思是原子地"测试和分配",而不是"原子分配".
如我们所知,compare_exchange_weak()如果存在竞争条件,则返回错误(错误值),因此无法完全执行操作.但是竞争条件究竟是如何确定的compare_exchange_weak()?
lock cmpxchg如果多一个线程尝试读/写值,即获取锁,并且确切地说这种方式compare_exchange_weak决定竞争条件,指令是否会返回错误?
以下示例来自MSDN。
public class ThreadSafe
{
// Field totalValue contains a running total that can be updated
// by multiple threads. It must be protected from unsynchronized
// access.
private float totalValue = 0.0F;
// The Total property returns the running total.
public float Total { get { return totalValue; }}
// AddToTotal safely adds a value to the running total.
public float AddToTotal(float addend)
{
float initialValue, computedValue;
do
{
// Save the current running total in a …Run Code Online (Sandbox Code Playgroud) 嘿,我正在科特林学习原子。我想知道在我的场景中使用原子布尔值是个好主意吗?有人可以建议如何以原子方式进行。
场景 1非首次通话
var isFirstTime = true
fun notForFirstTime(){
if(!isFirstTime){
jobDone()
}
isFirstTime = false
}
Run Code Online (Sandbox Code Playgroud)
场景2仅限第一次
var isFirstTime = true
fun onlyForFirstTime(){
if(isFirstTime){
jobDone()
}
isFirstTime = false
}
Run Code Online (Sandbox Code Playgroud)
我可以以原子方式做到这一点吗?这也是个好主意吗?