Share
Embed
Transcript
57 slides
-
目次 JavaVMにおけるロックの進化 トランザクショナルメモリ(TM)とは Haswellでのトランザクショナルメモリ Javaでトランザクショナルメモリを使う
JDK8/9の動向 まとめ 1 Copyright 2014 FUJITSU LIMITED -
2 Copyright 2014 FUJITSU LIMITED JavaVMロック機構の進化 第一世代 ヘビーロック 第二世代 シンロック
第三世代 バイアスロック 第四世代 ??? JDK1.0-1.2 JDK1.3.1 HotSpot VM JDK5.0 HotSpot VM -
競合と共有(定義) ロック競合とは 複数のスレッドが同時 に同じロックを取る ロック共有とは 複数のスレッドが同じ ロックを使用する 3
Copyright 2014 FUJITSU LIMITED スレッドA スレッドB ロックX獲得 ロックX待ち ロックXの競合 ロック競合している例 共有しているが競合していない例 スレッドA スレッドB ロックX獲得 ロックX解放 ロックX獲得 CS 実 行 CS 実 行 CS 実 行 -
競合と共有(定義) データ競合とは 複数のスレッドが同じ データにアクセスする こと、あるいは、アク セスするためのロック 競合 4 Copyright
2014 FUJITSU LIMITED synchronized(array) { array[1] = 2; } synchronized(array) { array[2] = 4; } スレッドA スレッドB ロック競合しているが データ競合していないコード例 ロック競合しているが データ競合していない例 スレッドA スレッドB ロックX獲得 ロックX待ち ロックの競合 アクセスY アクセスZ ロックX解放 ロックX獲得 データ競合なし CS 実 行 CS 実 行 -
ヘビーロック OSのロック関数(pthread_mutex_lock/unlock 等)を使用 実装が簡単なため、初期のJVMで使用 オブジェクト毎にmutexを作成・保持する必 要がある 5
Copyright 2014 FUJITSU LIMITED 管理ヘッダ mutex Javaオブジェクト mutex_t if(obj->mutex == null) { obj->mutex = malloc(…); … } pthread_mutex_lock(&obj->mutex); 本来の オブジェクト データ synchornizeの実装例 -
シンロック ほとんどのロックは競合してない CAS(Compare and Swap)で十分 マルチコア・メニーコアCPUでは、CASのコ ストはバカにならない
6 Copyright 2014 FUJITSU LIMITED ロック ビット Javaオブジェクト 管理ヘッダ mov 0, %R2 ld [ロックビット], %R1 cas [ロックビット], %R1, %R2 cmp %R1, %R2 jne ヘビーロック 通常処理 0:ロック 1:アンロック シンロック実装例 -
バイアスロック ほとんどのロックは共有されていない 特定のスレッド使うならロックする必要はない 最初(バイアスされていない時)だけCAS そのあとはLoad&Compare 7 Copyright
2014 FUJITSU LIMITED ld [バイアス情報], %R1 cmp %R1, 自分自身のスレッド jne バイアス無効処理 通常処理 バイアスされている場合の 実装例 StringBuffer sb = new StringBuffer(); sb.append(“abc”); sb.append(“def”); String str = sb.toString(); return str; バイアスロックの有効例 -
java.util.concurrentパッケージ JDK5.0から導入 synchronizeより柔軟なロック 8 Copyright 2014 FUJITSU LIMITED
import java.util.concurrent.locks.ReentrantLock; ReentrantLock lock = new ReentrantLock(); … public void m() { lock.lock(); try { //クリティカルセクションの実行 } finally { lock.unlock(); } tryLock() isLocked() getOwner() 使用例 便利なAPI (ReentrantLock) 便利なクラス ReadWriteLock Semaphore AtomicInteger -
目次 JavaVMにおけるロックの進化 トランザクショナルメモリ(TM)とは Haswellでのトランザクショナルメモリ Javaでトランザクショナルメモリを使う
JDK8/9の動向 まとめ 9 Copyright 2014 FUJITSU LIMITED -
トランザクショナルメモリとは 楽観的ロック とりあえず、ロックはしない 実行しているうちに、データ競合があった ら、それまでの実行結果を破棄( アボート )して、最初の状態にもどる(ロールバッ
ク) 最後までデータ競合がなければ、結果を確 定する(コミット) 10 Copyright 2014 FUJITSU LIMITED -
悲観的ロックと楽観的ロック 11 Copyright 2014 FUJITSU LIMITED 楽観的ロック 非観的ロック スレッド1 スレッド2
スレッド3 スレッド4 ロック ロック ロック ロック クリティカルセクションの実行はシリアライズ スレッド1 スレッド2 スレッド3 スレッド4 ロ ッ ク な し クリティカルセクションの実行は並行 -
HTMとSTM トランザクショナルメモリ(TM)をハード で実現するのをHTM、ソフトで実現するの をSTMと呼ぶ。 HTMの実装例 IBM System z
(zEC12) Intel Haswell Microarchitecture STMの実装例 Scala Haskell 12 Copyright 2014 FUJITSU LIMITED -
目次 JavaVMにおけるロックの進化 トランザクショナルメモリ(TM)とは Haswellでのトランザクショナルメモリ Javaでトランザクショナルメモリを使う
JDK8/9の動向 まとめ 13 Copyright 2014 FUJITSU LIMITED -
TSX Intel® Transactional Synchronization Extension IntelアーキテクチャでのHTM実装 Haswellで利用可能 HLEとRTMの2種類
Hardware Lock Elision 従来(mutex)方式と互換インタフェース Restricted Transaction Memory 新しいインタフェース 14 Copyright 2014 FUJITSU LIMITED -
HLE 従来のmutex_lock/mutex_unlockの形式でそ のまま置き換えられる アボートしたら、自動的にリトライ 15 Copyright 2014 FUJITSU
LIMITED mov $1, %eax RETRY: xacquire xchg mutex, %eax test %eax, %eax jne RETRY xrelease mov $0, mutex mutex_lock(&mutex); mutex_unlock(&mutex); クリティカルセクションの実行 クリティカルセクションの実行 従来(mutex) HLE -
GCC4.8からHLEサポート 16 Copyright 2014 FUJITSU LIMITED #include <immintrin.h> void lock_hle_gcc(int
*mutex) { while (__atomic_exchange_n(mutex, 1, __ATOMIC_ACQUIRE|__ATOMIC_HLE_ACQUIRE)) _mm_pause(); } void unlock_hle_gcc(int *mutex) { __atomic_clear(mutex, __ATOMIC_RELEASE|__ATOMIC_HLE_RELEASE); } 以下のような関数を自分で用意する(fallbackなし) int mutex = 0; void func() { lock_hle_gcc(&mutex); // クリティカルセクションの実行 unlock_hle_gcc(&mutex); クリティカルセクションを 上記2関数で挟む -
GCC4.8からHLEをサポート 17 Copyright 2014 FUJITSU LIMITED 0000000000000000 <lock_hle_gcc>: 0: ba
01 00 00 00 mov $0x1,%edx 5: eb 0b jmp 12 <lock_hle_gcc+0x12> 7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 10: f3 90 pause 12: 89 d0 mov %edx,%eax 14: f2 87 07 xacquire xchg %eax,(%rdi) 17: 85 c0 test %eax,%eax 19: 75 f5 jne 10 <lock_hle_gcc+0x10> 1b: f3 c3 repz retq 1d: 0f 1f 00 nopl (%rax) 0000000000000020 <unlock_hle_gcc>: 20: f3 c6 07 00 xrelease movb $0x0,(%rdi) 24: c3 retq ディスアセンブルするには、新しいobjdump(binutils)が必要 -
RTM アボートした時のハンドラ―を自分で書く 必要あり 18 Copyright 2014 FUJITSU LIMITED RETRY:
xbegin FAIL cmp mutex, $0 jz OK FAIL: # goto RETRY or SLOWPATH SLOWPATH: # original code OK: ret cmp mutex, $0 jne SLOWPATH xend ret SLOWPATH: # original code ロックコード アンロックコード -
いつアボートするか トランザクションが長い I/Oが入る OSによるスレッドコンテキストスイッチ 特殊な命令を実行(CPUID/XABORT)
ネストが深すぎる L1キャッシュラインの競合 19 Copyright 2014 FUJITSU LIMITED -
Haswellのキャッシュ L1 Instruction Cache 32KB 8-way L1 Data
Cache 32KB 8-way コアごと(スレッドで共有) L2 Unified Cache 256KB 8-way コアごと(スレッドで共有) キャッシュライン 64B 20 Copyright 2014 FUJITSU LIMITED 64バイト 64バイト 64バイト 64バイト L1 Data Cache 64個 8-way -
キャッシュラインの競合 TSXでは、L1キャッシュラインでデータ競合 を検出 21 Copyright 2014 FUJITSU LIMITED xbegin
FAIL mov (0x1000), %eax xend スレッドA xbegin FAIL mov %eax, (0x1010) xend スレッドB 0x1000 0x1010 0x1004 0x1008 0x1040 アドレス 同 一 キ ャ ッ シ ュ ラ イ ン 競合 -
目次 JavaVMにおけるロックの進化 トランザクショナルメモリ(TM)とは Haswellでのトランザクショナルメモリ Javaでトランザクショナルメモリを使う
JDK8/9の動向 まとめ 22 Copyright 2014 FUJITSU LIMITED -
synchronizeの実装 アプリの修正が不要 個別に指定できない 競合あるところはTMは向いていないので、従来 実装を使いたい 競合のないところは、TM実装を使いたい 実装するのがたいへん
JVM(HotSpot)の中でかなりの部分に影響 24 Copyright 2014 FUJITSU LIMITED -
APIとして提供 アプリ修正が必要 選択的に使用可能 使う側がどういう場合にTMが向いているか 理解している必要あり 使用方法はReentrantLockと同じ
実装はsyhchronizeほどではないが、比較的 たいへん。 25 Copyright 2014 FUJITSU LIMITED -
特定ライブラリでの実装 アプリ修正は不要 使いたいところで使えない 例 java.util.HashMap/ArrayList/LinkedList 26 Copyright
2014 FUJITSU LIMITED table HashMap Entryテーブル Key Value Key Value -
API方式での実装 27 Copyright 2014 FUJITSU LIMITED public final class HTM
{ private ByteBuffer data; private long mutex_addr; public HTM() { data = ByteBuffer.allocateDirect(64); mutex_addr = nativeAddress(data); } public void lock() { lockRTM(mutex_addr); } public void unlock() { unlockRTM(mutex_addr); } static private native void lockRTM(long addr); static private native void unlockRTM(long addr); 使用方法 HTM htm = new HTM(); htm.lock(); // クリティカル //セクションの実行 htm.unlock(); -
HTMクラスの構造 28 Copyright 2014 FUJITSU LIMITED ByteBuffer data HTM 64バイト
long mutex_addr Javaヒープ Cヒープ DirectByteBuffer ・・・ long address allocateDirect(64) mutex -
ネイティブメソッド(C) 29 Copyright 2014 FUJITSU LIMITED #include <jni.h> void java_htm_lock_rtm(jlong);
void java_htm_unlock_rtm(jlong); JNIEXPORT void JNICALL Java_HTM_lockRTM(JNIEnv *env, jclass kl, jlong add) { java_htm_lock_rtm(add); } JNIEXPORT void JNICALL Java_HTM_unlockRTM(JNIEnv *env, jclass kl, jlong add) { java_htm_unlock_rtm(add); } -
ネイティブメソッド(asm) 30 Copyright 2014 FUJITSU LIMITED # void java_htm_lock_rtm(jlong) java_htm_lock_rtm:
movl $10, %ecx #retry count .RETRY: xbegin .FAIL cmpl $0, (%rdi) jz .OK xabort $0xfe .FAIL: pause dec %ecx cmpl $0, %ecx jz .SLOWPATH jmp .RETRY .SLOWPATH: xor %edx, %edx inc %edx xor %eax, %eax lock cmpxchgl %edx, (%rdi) jne .SLOWPATH .OK: ret # void java_htm_unlock_rtm(jlong) java_htm_unlock_rtm: cmpl $0, (%rdi) jz .END movl $0, (%rdi) ret .END: xend ret -
データ競合なしプログラム 本来ロックを取る必要のないプログラムで のベンチマーク 一定量(500,000,000回)スレッドローカルな 変数をインクリメントする スレッド数を1から8まで増やす
各スレッドに均等な処理量を分割する 各スレッドの処理時間の平均を求める 「排他なし」、「synchronized」、 「ReentrantLock」「HTM」の4パターン 31 Copyright 2014 FUJITSU LIMITED -
データ競合なしプログラム 32 Copyright 2014 FUJITSU LIMITED class LockNone extends Test
{ LockNone(long amount) { this.amount = amount; } void doIt() { count++; } } abstract class Test implements Runnable { long count; long time; long amount; public void run() { count = 0; long start = System.currentTimeMillis(); while (count < amount) { doIt(); } long end = System.currentTimeMillis(); time = (end-start); } } 排他なし -
データ競合なしプログラム 33 Copyright 2014 FUJITSU LIMITED class LockSync extends Test
{ Object lock; LockSync(long amount, Object lock) { this.amount = amount; this.lock = lock; } void doIt() { synchronized (lock) { count++; } } } synchronized使用 -
データ競合なしプログラム 34 Copyright 2014 FUJITSU LIMITED class LockConc extends Test
{ ReentrantLock lock; LockConc(long amount, ReentrantLock lock) { this.amount = amount; this.lock = lock; } void doIt() { lock.lock(); count++; lock.unlock(); } } ReentrantLock使用 -
データ競合なしプログラム 35 Copyright 2014 FUJITSU LIMITED class LockRTM extends Test
{ HTM htm; LockRTM(long amount, HTM htm) { this.amount = amount; this.htm = htm; } void doIt() { htm.lock(); count++; htm.unlock(); } } HTM使用 -
データ競合なし(結果) 36 Copyright 2014 FUJITSU LIMITED 1スレッドあたりの平均処理時間 JDK1.7.0_51 Intel Xeon
E3-1270 v3 3.5GHz Red Hat Enterprise Linux Server release 6.5 (Santiago) -
ネイティブメソッド呼出し ネイティブメソッドの呼び出しはコストが 高い 性能高速化のために、Javaでかけるコード をCにしても、速くなるとは限らない 37 Copyright 2014
FUJITSU LIMITED Java メソッド ネイティブ メソッド スタブ コード 直接呼べない -
スタブコード(unlockRTM) 38 Copyright 2014 FUJITSU LIMITED Decoding compiled method 0x00007f12dd05ebd0:
Code: [Disassembling for mach='i386:x86-64'] [Entry Point] # {method} 'unlockRTM' '(J)V' in 'HTM' # parm0: rsi:rsi = long # [sp+0x50] (sp of caller) 0x00007f12dd05ed60: mov 0x8(%rsi),%r10d 0x00007f12dd05ed64: cmp %r10,%rax 0x00007f12dd05ed67: je 0x00007f12dd05ed78 0x00007f12dd05ed6d: jmpq 0x00007f12dd037960 ; {runtime_call} 0x00007f12dd05ed72: nopw 0x0(%rax,%rax,1) [Verified Entry Point] 0x00007f12dd05ed78: mov %eax,-0x14000(%rsp) 0x00007f12dd05ed7f: push %rbp 0x00007f12dd05ed80: mov %rsp,%rbp 0x00007f12dd05ed83: sub $0x40,%rsp 0x00007f12dd05ed87: mov %rsi,%rdx 0x00007f12dd05ed8a: movabs $0xdff84370,%r14 ; {oop(a 'java/lang/Class' = 'HTM')} 0x00007f12dd05ed94: mov %r14,0x30(%rsp) 0x00007f12dd05ed99: lea 0x30(%rsp),%r14 0x00007f12dd05ed9e: mov %r14,%rsi ; OopMap{[48]=Oop off=65} 0x00007f12dd05eda1: movabs $0x7f12dd05eda1,%r10 ; {section_word} 0x00007f12dd05edab: mov %r10,0x1c0(%r15) 0x00007f12dd05edb2: mov %rsp,0x1b8(%r15) 0x00007f12dd05edb9: cmpb $0x0,0x8ef495a(%rip) # 0x00007f12e5f5371a ; {external_word} 0x00007f12dd05edc0: je 0x00007f12dd05edfa 0x00007f12dd05edc6: push %rsi 0x00007f12dd05edc7: push %rdx 0x00007f12dd05edc8: movabs $0xdafd0040,%rsi ; {oop({method} 'unlockRTM' '(J)V' in 'HTM')} 0x00007f12dd05edd2: mov %r15,%rdi 0x00007f12dd05edd5: test $0xf,%esp 0x00007f12dd05eddb: je 0x00007f12dd05edf3 0x00007f12dd05ede1: sub $0x8,%rsp 0x00007f12dd05ede5: callq 0x00007f12e59c4230 ; {runtime_call} 0x00007f12dd05edea: add $0x8,%rsp 0x00007f12dd05edee: jmpq 0x00007f12dd05edf8 0x00007f12dd05edf3: callq 0x00007f12e59c4230 ; {runtime_call} 0x00007f12dd05edf8: pop %rdx 0x00007f12dd05edf9: pop %rsi 0x00007f12dd05edfa: lea 0x1d8(%r15),%rdi 0x00007f12dd05ee01: movl $0x4,0x250(%r15) 0x00007f12dd05ee0c: callq 0x00007f12da7ef660 ; {runtime_call} 0x00007f12dd05ee11: vzeroupper 0x00007f12dd05ee14: movl $0x5,0x250(%r15) 0x00007f12dd05ee1f: mov %r15d,%ecx 0x00007f12dd05ee22: shr $0x4,%ecx 0x00007f12dd05ee25: and $0xffc,%ecx 0x00007f12dd05ee2b: movabs $0x7f12e61ac000,%r10 ; {external_word} 0x00007f12dd05ee35: mov %ecx,(%r10,%rcx,1) 0x00007f12dd05ee39: cmpl $0x0,0x8efd83d(%rip) # 0x00007f12e5f5c680 ; {external_word} 0x00007f12dd05ee43: jne 0x00007f12dd05ee57 0x00007f12dd05ee49: cmpl $0x0,0x30(%r15) 0x00007f12dd05ee51: je 0x00007f12dd05ee74 0x00007f12dd05ee57: mov %r15,%rdi 0x00007f12dd05ee5a: mov %rsp,%r12 0x00007f12dd05ee5d: sub $0x0,%rsp 0x00007f12dd05ee61: and $0xfffffffffffffff0,%rsp 0x00007f12dd05ee65: callq 0x00007f12e5a655a0 ; {runtime_call} 0x00007f12dd05ee6a: mov %r12,%rsp 0x00007f12dd05ee6d: mov 0x8ed8f3c(%rip),%r12 # 0x00007f12e5f37db0 ; {external_word} 0x00007f12dd05ee74: movl $0x8,0x250(%r15) 0x00007f12dd05ee7f: cmpl $0x1,0x27c(%r15) 0x00007f12dd05ee8a: je 0x00007f12dd05ef13 0x00007f12dd05ee90: cmpb $0x0,0x8ef4883(%rip) # 0x00007f12e5f5371a ; {external_word} 0x00007f12dd05ee97: je 0x00007f12dd05eecd 0x00007f12dd05ee9d: movabs $0xdafd0040,%rsi ; {oop({method} 'unlockRTM' '(J)V' in 'HTM')} 0x00007f12dd05eea7: mov %r15,%rdi 0x00007f12dd05eeaa: test $0xf,%esp 0x00007f12dd05eeb0: je 0x00007f12dd05eec8 0x00007f12dd05eeb6: sub $0x8,%rsp 0x00007f12dd05eeba: callq 0x00007f12e59c4380 ; {runtime_call} 0x00007f12dd05eebf: add $0x8,%rsp 0x00007f12dd05eec3: jmpq 0x00007f12dd05eecd 0x00007f12dd05eec8: callq 0x00007f12e59c4380 ; {runtime_call} 0x00007f12dd05eecd: movabs $0x0,%r10 0x00007f12dd05eed7: mov %r10,0x1b8(%r15) 0x00007f12dd05eede: movabs $0x0,%r10 0x00007f12dd05eee8: mov %r10,0x1c0(%r15) 0x00007f12dd05eeef: mov 0x38(%r15),%rcx 0x00007f12dd05eef3: movq $0x0,0x100(%rcx) 0x00007f12dd05eefe: leaveq 0x00007f12dd05eeff: cmpq $0x0,0x8(%r15) 0x00007f12dd05ef07: jne 0x00007f12dd05ef0e 0x00007f12dd05ef0d: retq 0x00007f12dd05ef0e: jmpq Stub::forward exception ; {runtime_call} 0x00007f12dd05ef13: mov %rsp,%r12 0x00007f12dd05ef16: sub $0x0,%rsp 0x00007f12dd05ef1a: and $0xfffffffffffffff0,%rsp 0x00007f12dd05ef1e: callq 0x00007f12e59c3600 ; {runtime_call} 0x00007f12dd05ef23: mov %r12,%rsp 0x00007f12dd05ef26: mov 0x8ed8e83(%rip),%r12 # 0x00007f12e5f37db0 ; {external_word} 0x00007f12dd05ef2d: jmpq 0x00007f12dd05ee90 0x00007f12dd05ef32: hlt -
native intrinsic ネイティブメソッドをJITが翻訳したコード のように扱う インライン展開することで、スタブが不要 40 Copyright 2014
FUJITSU LIMITED Java ソース Cソース .class .so/.dll 翻訳 コード javac Cコンパイラ jit スタブ経由の 呼出し 同等コード アセンブラ 翻訳 コード 取込み -
intrinsicコード(lock) 41 Copyright 2014 FUJITSU LIMITED instruct htm_lock_rtm( memory adr,
rax_RegI result, rcx_RegI tmp) %{ match(HtmRtmLock adr); ins_encode %{ Label retry, fail, ok, slowpath; __ movl($tmp$$Register, 10); __ bind(retry); __ xbegin(fail); __ cmpl($adr$$Address, 0); __ jccb(Assembler::equal, ok); __ xabort(0xfe); __ bind(fail); __ pause(); __ decrementl($tmp$$Register); __ cmpl($tmp$$Register, 0); __ jccb(Assembler::equal, slowpath); __ jmp(retry); __ bind(slowpath); __ movl($tmp$$Register, 1); __ movl($result$$Register, 0); __ lock(); __ cmpxchgl($tmp$$Register, $adr$$Address); __ jccb(Assembler::notEqual, slowpath); __ bind(ok); hotspot/src/cpu/x86/vm/x86_64.ad -
intrinsicコード(unlock) 42 Copyright 2014 FUJITSU LIMITED instruct htm_unlock_rtm(memory adr, rax_RegI
result) %{ match(HtmRtmUnlock adr); ins_encode %{ Label end, done; __ cmpl($adr$$Address, 0); __ jccb(Assembler::equal, end); __ movl($adr$$Address, 0); __ jmp(done); __ bind(end); __ xend(); __ bind(done); hotspot/src/cpu/x86/vm/x86_64.ad -
データ競合なし(結果) 43 Copyright 2014 FUJITSU LIMITED 1スレッドあたりの平均処理時間 JDK1.7.0_51 Intel Xeon
E3-1270 v3 3.5GHz Red Hat Enterprise Linux Server release 6.5 (Santiago) -
データ競合あるかもプログラム ArrayListアクセス時にロックを取るプログ ラムでのベンチマーク 全部で一定回数(100,000,000回)、ArrayListの 連続した2要素を入れ替える 入れ替える場所はランダムに決める
配列要素は十分大きい スレッド数を1から8まで増やす 各スレッドに均等な処理量を分割する 各スレッドの処理時間の平均を求める 44 Copyright 2014 FUJITSU LIMITED -
データ競合あるかもプログラム 45 Copyright 2014 FUJITSU LIMITED static long AMOUNT =
100_000_000L; static int ARRAY_SIZE = 131_072; static ArrayList<Object> alist = new ArrayList<>(ARRAY_SIZE); abstract class Test implements Runnable { long count; long time; long amount; long seed; public void run() { count = 0; long start = System.currentTimeMillis(); while (count < amount) { int n1 = nextInt(ARRAY_SIZE); int n2 = n1+1; if (n2 == ARRAY_SIZE) n2 -= 2; doIt(n1, n2); count++; } long end = System.currentTimeMillis(); time = (end-start); } void swap(int n1, int n2) { Object o1 = alist.get(n1); Object o2 = alist.get(n2); alist.set(n1, o2); alist.set(n2, o1); } int nextInt(int n) { long nextseed = (seed * 0x5deece66dL + 0xbL) & ((1L << 48) - 1); long rnd31 = nextseed >>> (48-31); seed = nextseed; return (int) ((n * rnd31) >> 31); } -
データ競合あるかもプログラム 46 Copyright 2014 FUJITSU LIMITED void doIt(int n1, int
n2) { synchronized (lock) { swap(n1, n2); } } void doIt(int n1, int n2) { lock.lock(); try { swap(n1, n2); } finally { lock.unlock(); } } void doIt(int n1, int n2) { swap(n1, n2); } void doIt(int n1, int n2) { htm.lock(); try { swap(n1, n2); } finally { htm.unlock(); } } 排他なし HTM synchronized ReentrantLock -
データ競合あるかも(結果) 47 Copyright 2014 FUJITSU LIMITED 1スレッドあたりの平均処理時間 JDK1.7.0_51 Intel Xeon
E3-1270 v3 3.5GHz Red Hat Enterprise Linux Server release 6.5 (Santiago) -
目次 JavaVMにおけるロックの進化 トランザクショナルメモリ(TM)とは Haswellでのトランザクショナルメモリ Javaでトランザクショナルメモリを使う
JDK8/9の動向 まとめ 48 Copyright 2014 FUJITSU LIMITED -
JDK8/9の動向 -XX:+UseRTMLocking https://bugs.openjdk.net/browse/JDK-8031320 synchronizeの実装として使用 メソッド毎に有効・無効を指定する仕組みはあ りそう バイアスロックとは排他関係
性能は? 49 Copyright 2014 FUJITSU LIMITED -
目次 JavaVMにおけるロックの進化 トランザクショナルメモリ(TM)とは Haswellでのトランザクショナルメモリ Javaでトランザクショナルメモリを使う
JDK8/9の動向 まとめ 51 Copyright 2014 FUJITSU LIMITED -
JavaでTMが有効なケース ロック共有しているが、ロック競合がない バイアスロックが不向きなパターン ロック競合はあるが、データ競合がない 本来プログラム的にはロックの必要がなく、安 心のためだけにロックを入れている ロック競合はあるが、ほとんどデータ競合
せず、たまに競合する場合がある ArrayListのパターン 52 Copyright 2014 FUJITSU LIMITED -
JavaでTMの効果ないケース ロック競合がほとんど起きていない ロック期間が長い バッファ枯渇やコンテキストスイッチ ロック中にIOあり デバッグは難しい
ロック中にGCあり 共有しないロックを何度も使う バイアスロックがよい 53 Copyright 2014 FUJITSU LIMITED -
55 Copyright 2014 FUJITSU LIMITED Javaは、Oracle Corporationおよびその子会社、関連会社の米国および その他の国おける登録商標です。 本ドキュメントに記載されている、社名、商品名等は各社の商標または 登録商標である場合があります。
その他の記載されている、商標および登録商標については、 一般に各社の商標または登録商標です。