zio/zio2

Ref vs Ref.Synchronized

wefree 2022. 12. 9. 19:30

RefRef.Synchronized 의 차이는 무엇일까?

Ref

update function may be run more than once

import zio._

object RefApp extends zio.ZIOAppDefault {
  def demo: UIO[Unit] = {
    def task(id: Int, ref: Ref[Int]): UIO[Unit] =
      ref.modify(prev => (println(s"Task $id updating ref at $prev"), id))

    for {
      ref <- Ref.make(0)
      _   <- ZIO.collectAllParDiscard((1 to 5).toList.map(i => task(i, ref)))
    } yield ()
  }

  override def run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] = demo
}

 

실행 결과

lock 획득을 위해 retry 가 내부적으로 일어나 4번 이상 수행되었다.

Task1 --> Task5 --> Task3 --> Task2 --> Task4 순으로 ref state 를 업데이트 했다.

Task 1 updating ref at 0
Task 3 updating ref at 0
Task 5 updating ref at 0
Task 4 updating ref at 0
Task 5 updating ref at 1
Task 3 updating ref at 1
Task 3 updating ref at 5
Task 2 updating ref at 0
Task 4 updating ref at 1
Task 2 updating ref at 3
Task 4 updating ref at 3
Task 4 updating ref at 2

 

Ref.Synchronized

import zio._

object RefSynchronizedApp extends zio.ZIOAppDefault {
  def demo: UIO[Unit] = {
    def task(id: Int, ref: Ref[Int]): UIO[Unit] =
      ref.modify(prev => (println(s"Task $id updating ref at $prev"), id))

    for {
      ref <- Ref.Synchronized.make(0)
      _   <- ZIO.collectAllParDiscard((1 to 5).toList.map(i => task(i, ref)))
    } yield ()
  }

  override def run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] = demo
}

 

실행 결과

정확히 5번 수행된다.

Task 3 updating ref at 0
Task 5 updating ref at 3
Task 2 updating ref at 5
Task 4 updating ref at 2
Task 1 updating ref at 4