ใน Intel การอ่านค่าระเหยที่ไม่ได้โต้แย้งนั้นค่อนข้างถูก หากเราพิจารณากรณีง่ายๆดังต่อไปนี้:
public static long l;
public static void run() {
if (l == -1)
System.exit(-1);
if (l == -2)
System.exit(-1);
}
การใช้ความสามารถของ Java 7 ในการพิมพ์รหัสแอสเซมบลีวิธีการรันจะมีลักษณะดังนี้:
# {method} 'run2' '()V' in 'Test2'
# [sp+0x10] (sp of caller)
0xb396ce80: mov %eax,-0x3000(%esp)
0xb396ce87: push %ebp
0xb396ce88: sub $0x8,%esp ;*synchronization entry
; - Test2::run2@-1 (line 33)
0xb396ce8e: mov $0xffffffff,%ecx
0xb396ce93: mov $0xffffffff,%ebx
0xb396ce98: mov $0x6fa2b2f0,%esi ; {oop('Test2')}
0xb396ce9d: mov 0x150(%esi),%ebp
0xb396cea3: mov 0x154(%esi),%edi ;*getstatic l
; - Test2::run@0 (line 33)
0xb396cea9: cmp %ecx,%ebp
0xb396ceab: jne 0xb396ceaf
0xb396cead: cmp %ebx,%edi
0xb396ceaf: je 0xb396cece ;*getstatic l
; - Test2::run@14 (line 37)
0xb396ceb1: mov $0xfffffffe,%ecx
0xb396ceb6: mov $0xffffffff,%ebx
0xb396cebb: cmp %ecx,%ebp
0xb396cebd: jne 0xb396cec1
0xb396cebf: cmp %ebx,%edi
0xb396cec1: je 0xb396ceeb ;*return
; - Test2::run@28 (line 40)
0xb396cec3: add $0x8,%esp
0xb396cec6: pop %ebp
0xb396cec7: test %eax,0xb7732000 ; {poll_return}
;... lines removed
หากคุณดูการอ้างอิง 2 รายการเพื่อ getstatic รายการแรกเกี่ยวข้องกับการโหลดจากหน่วยความจำส่วนที่สองจะข้ามการโหลดเนื่องจากค่าถูกนำมาใช้ใหม่จากการลงทะเบียนที่โหลดไว้แล้ว (ยาวคือ 64 บิตและบนแล็ปท็อป 32 บิตของฉัน ใช้การลงทะเบียน 2 รายการ)
ถ้าเราทำให้ตัวแปร l ระเหยการประกอบผลลัพธ์จะแตกต่างกัน
# {method} 'run2' '()V' in 'Test2'
# [sp+0x10] (sp of caller)
0xb3ab9340: mov %eax,-0x3000(%esp)
0xb3ab9347: push %ebp
0xb3ab9348: sub $0x8,%esp ;*synchronization entry
; - Test2::run2@-1 (line 32)
0xb3ab934e: mov $0xffffffff,%ecx
0xb3ab9353: mov $0xffffffff,%ebx
0xb3ab9358: mov $0x150,%ebp
0xb3ab935d: movsd 0x6fb7b2f0(%ebp),%xmm0 ; {oop('Test2')}
0xb3ab9365: movd %xmm0,%eax
0xb3ab9369: psrlq $0x20,%xmm0
0xb3ab936e: movd %xmm0,%edx ;*getstatic l
; - Test2::run@0 (line 32)
0xb3ab9372: cmp %ecx,%eax
0xb3ab9374: jne 0xb3ab9378
0xb3ab9376: cmp %ebx,%edx
0xb3ab9378: je 0xb3ab93ac
0xb3ab937a: mov $0xfffffffe,%ecx
0xb3ab937f: mov $0xffffffff,%ebx
0xb3ab9384: movsd 0x6fb7b2f0(%ebp),%xmm0 ; {oop('Test2')}
0xb3ab938c: movd %xmm0,%ebp
0xb3ab9390: psrlq $0x20,%xmm0
0xb3ab9395: movd %xmm0,%edi ;*getstatic l
; - Test2::run@14 (line 36)
0xb3ab9399: cmp %ecx,%ebp
0xb3ab939b: jne 0xb3ab939f
0xb3ab939d: cmp %ebx,%edi
0xb3ab939f: je 0xb3ab93ba ;*return
;... lines removed
ในกรณีนี้การอ้างอิงทั้งสองแบบ getstatic ไปยังตัวแปร l เกี่ยวข้องกับการโหลดจากหน่วยความจำกล่าวคือไม่สามารถเก็บค่าไว้ในรีจิสเตอร์ในการอ่านค่าระเหยหลาย ๆ เพื่อให้แน่ใจว่ามีการอ่านค่าอะตอมค่าจะถูกอ่านจากหน่วยความจำหลักไปยังการลงทะเบียน MMX movsd 0x6fb7b2f0(%ebp),%xmm0
ทำให้การดำเนินการอ่านเป็นคำสั่งเดียว (จากตัวอย่างก่อนหน้านี้เราเห็นว่าปกติค่า 64 บิตจะต้องอ่าน 32 บิตสองครั้งในระบบ 32 บิต)
ดังนั้นค่าใช้จ่ายโดยรวมของการอ่านแบบระเหยจะเทียบเท่ากับการโหลดหน่วยความจำโดยประมาณและอาจถูกพอ ๆ กับการเข้าถึงแคช L1 อย่างไรก็ตามหากคอร์อื่นกำลังเขียนไปยังตัวแปรระเหยแคชบรรทัดจะไม่ถูกต้องโดยต้องใช้หน่วยความจำหลักหรืออาจเข้าถึงแคช L3 ต้นทุนจริงจะขึ้นอยู่กับสถาปัตยกรรมของ CPU เป็นอย่างมาก แม้ระหว่าง Intel และ AMD โปรโตคอลการทำงานร่วมกันของแคชจะแตกต่างกัน