-
Couldn't load subscription status.
- Fork 8
wmi review3
myeongin edited this page Jun 13, 2016
·
5 revisions
lazy라는 키워드는 값이 실제 필요할 때까지 계산을 유예해야 함을 표시한다. method와 차이점이 있다면 method는 호출 될때마다 연산을 재 실행 하지만 lazy 는 최초에만 연산이 수행되고 이후에는 재 사용 된다.
scala> object Demo {
lazy val x = { println("initializing x"); "done" }
}
defined module Demo
scala> Demo
res5: Demo.type = Demo$@11dda2d
scala> Demo.x
initializing x
res6: java.lang.String = donelazy는 두번 계산하지 않는다. 실제로 재 호출 된다면 이전에 저장 했던 값을 재 사용한다.
scala> val x = { println("x"); 15 }
x
x: Int = 15
scala> lazy val y = { println("y"); 13 }
y: Int = <lazy>
scala> x
res2: Int = 15
scala> y
y
res3: Int = 13
scala> y
res4: Int = 13그렇다면 모든 변수를 lazy로 만드는 것이 더 좋지 않은가? 실제로는 비용이 비싼 경우가 아니라면 속도가 빠르지 않기 때문이다.
지연값은 가드를 사용한다.
가드를 사용해서 지연값이 초기화되었는지 여부를 저장해둔 볼러틀(volatile) 필드를 검사하고, 꼭 필요할 때만 지연값을 초기화한다. 또한 초기화하는 과정에서는 이중 검사 락(double checked locking)을 사용해서 혹시 다중 스레드 환경 등에서 이중으로 지연값이 초기화되지 않게 보장한다. 다만 여기에는 성능문제 이외에 다른 단점이 존재한다.
이중 검사 락에서는 지연값이 들어 있는 객체를 모니터로 사용한다. 따라서 지연값이 여럿 들어있는 객체를 사용하는 여러 스레드가 동시에 여러 지연값을 참조하거나, 한 스레드가 지연값을 갱신하는 사이에 다른 스레드가 지연값이 들어 있는 개체에 대해 synchronized를 실행하는 경우 교착상태에 빠질 수 있다.