【Kotlin/Android】AtomicIntegerでスレッドセーフにカウンターを扱う方法

【Kotlin/Android】AtomicIntegerでスレッドセーフにカウンターを扱う方法

この記事からわかること

  • Android Studio/KotlinAtomicInteger使い方
  • スレッドセーフカウンター実装するには?
  • synchronizedの使い方

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

Kotlinで異なるスレッドからの操作の注意点

Kotlinで異なるスレッドから変更を加えるような実装にすると期待する通りに反映されないことがあります。例えば以下のように100個のスレッドからcounterを参照してインクリメントさせる実装では結果が100000になるはずですが、出力結果は少し欠落した値になってしまっています。

var counter = 0

val threads = List(100) {
    thread {
        repeat(1000) {
            counter++
        }
    }
}

threads.forEach { it.join() }

println("Final counter value: $counter")
// Final counter value: 98298

この結果は予期せぬバグの温床になるので異なるスレッドから値を参照する際は適切に管理する必要があります。

AtomicInteger

AtomicIntegerスレッドセーフな整数型です。先ほどの問題はこのAtomicIntegerを使用することで解決できました。

val counter = AtomicInteger(0)

val threads = List(100) {
    thread {
        repeat(1000) {
            counter.incrementAndGet()
        }
    }
}

threads.forEach { it.join() }

println("Final counter value: ${counter.get()}")
// Final counter value: 100000

ここからはAtomicIntegerの使い方をまとめていきます。

インスタンス化

インスタンス化するにはAtomicIntegerのコンストラクタを使用します。

val counter = AtomicInteger(0)

値の取得

現在の値を取得するにはgetメソッドを使用します。

val count = counter.get()

新しい値を設定

新しい値を設定するにはsetメソッドを使用します。

counter.set(10)

インクリメントして取得

インクリメントして取得するにはincrementAndGetメソッドを使用します。

val count = counter.incrementAndGet()

デクリメントして取得

デクリメントして取得するにはdecrementAndGetメソッドを使用します。

val count = counter.decrementAndGet()

指定した値を加算して取得

指定した値を加算して取得するにはaddAndGetメソッドを使用します。

val count = counter.addAndGet(4)

指定した値なら指定した値に更新して取得

指定した値なら指定した値に更新して取得するにはcompareAndSet(int expect, int update)メソッドを使用します。

val wasUpdated = counter.compareAndSet(15, 20)

synchronizedで同期化

スレッドセーフにカウンターを扱う方法としてsynchronizedブロックを使用することで期待通りに動作させることも可能です。

var counter = 0
val lock = Any()

val threads = List(100) {
    thread {
        repeat(1000) {
            synchronized(lock) {
                counter++
            }
        }
    }
}

threads.forEach { it.join() }

println("Final counter value: $counter")
// Final counter value: 100000

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index