【Kotlin/Android】ReentrantLock/ReentrantReadWriteLockでスレッドセーフ(排他制御)の実装方法

この記事からわかること
- Android Studio/Kotlinでスレッドセーフ(排他制御)を実装するには?
- ReentrantLock/ReentrantReadWriteLockの使い方
\ アプリをリリースしました /
環境
- Android Studio:Meerkat
- Kotlin:2.0.21
- Mac M1:Sequoia 15.4
スレッドセーフ(排他制御)な実装
Kotlinで複数のスレッドからの同時アクセスを防ぐための手段はいくつか存在します。今回はその中でもReentrantLock
/ReentrantReadWriteLock
の使い方をまとめていきます。
ReentrantLock
ReentrantLock
を使用して排他制御を行うにはReentrantLock
をインスタンス化して、スレッドセーフにしたい処理の前にlock
/unlock
メソッドを使用してロック/アンロックします。unlock
を呼び忘れるとデッドロック状態になってしまうのでtry ~ finally
構文を使用して処理の最後に必ず呼ばれるような仕組みにしておいた方が安全です。
他のスレッドで処理を実行中でReentrantLock
がロックされている状態の場合に別のスレッドからlock
を呼び出すとロック中のスレッドからの処理がアンロックされるまで待機します。
例えば上記のように実行した場合でも出力は期待通りにインクリメントされて動作します。ただこれをスレッドセーフ機構を使用しないとスレッドBのsafeIncrement
が先に実行されスレッドBの出力はThread-B END 1
になってしまいます。
アンロックを待機しない
別スレッドでの処理中の場合にアンロックを待機したくない場合はtryLock
メソッドを使用します。Boolean
でロック中かどうかを取得することができるのでハンドリングしてあげればOKです。
tryLock
の引数には待機秒数を指定することが可能です。
複数回のロックとロックなしでのアンロック
lock
メソッドは複数回実行することが可能になっています。呼び出した分だけロックされてしまうので解除する際もロックした回数分unlock
を呼び出す必要があります。
またlock
を呼んでいないのにunlock
を呼び出すとjava.lang.IllegalMonitorStateException
をスローします。
ReentrantReadWriteLock
ReentrantReadWriteLock
もスレッドアクセスをブロックできる機構も持っていますが「複数のスレッドから同時の取得は許可し、書込は排他制御」を行うことが特徴です。
使用方法はReentrantReadWriteLock
をインスタンス化し、readLock
で読込用のロック機構をwriteLock
で書込用のロック機構を取得します。
読み込みを行いたい場合はreadLock.lock()
でロックします。読み込みは複数スレッドからでもアクセスは可能ですが、読み込み中に書き込まれないようにロックします。
書き込みを行いたい場合はwriteLock.lock()
でロックします。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。