LoginSignup
1
0

More than 1 year has passed since last update.

Scalaの勉強はじめました 12 〜スレッドセーフ〜

Posted at

はじめに

N予備校で「Scala基礎」「Scala応用」「並行処理プログラミング」を受講しています。今回からしばらくは並行処理についてになります。

並行性

マルチプロセスやマルチスレッドで実現している CPU のリソース数に限らず、複数の数のタスクを実行する性質のこと

object ThreadTest extends App {  
  println(Thread.currentThread().getName)

  val thread = new Thread(() => {
    Thread.sleep(1000)
    println(Thread.currentThread().getName)
  })
  thread.start()

  println("main thread finished.")
}

currentThreadは現在の処理が実行しているスレッドのインスタンスを取得する。

synchronizedブロック

object ThreadRisk extends App {
  private var counter = 0

  def next(): Int = synchronized {
    counter = counter + 1
    counter
  }
  for (i <- 1 to 10) {
    new Thread(() => {
      for (j <- 1 to 100000) {
        println(next())
      }
    }).start()
  }
}

一つしかこの処理を通らないようにする、アトミックに行われることを保証する。

一連の処理を原子のようにこれ以上分解できない単一の単位処理として行うことを、アトミックな処理という。

スレッドセーフ

複数のスレッドで操作した場合に正しく動かない実装の状態のことを「スレッドセーフではない」という。

・可変の状態を複数のスレッドが共有しないようにする
・可変の状態を不変にする
・可変の状態へのアクセスを常に同期化する

このいずれかを対処し、マルチスレッドへの対応がされたオブジェクトやクラスなどがスレッドセーフという。

object CheckThenAct extends App {
  for (i <- 1 to 100) {
    new Thread(() => {
      println(SingletonProvider.get)
    }).start()
  }
}
object SingletonProvider {
  private[this] var singleton: BigObject = null

  def get: BigObject = this.synchronized {
    if (singleton == null) {
      singleton = new BigObject()
    }
    singleton
  }
}
class BigObject() {
  Thread.sleep(1000)
}

this synchronized
thisというインスタンスでロックを取得する。

ロックとは、その処理が指定したインスタンスで1 つしか実行されないように カギをかけること

まとめ

ロックした処理の中で重い処理を実行した場合、全体のパフォーマンスにも関わってくるので、synchronizedを使う時は注意が必要、とのこと。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0