Testing Promises vs Lock performance I'm not sure if my lock usage is correct and safe. I wanted to know what will be best approach to deal with situation when one thread have to wait for being initialized by another so I written this test:

import java.util.concurrent.locks.ReentrantLock
import java.util.{TimerTask, Timer, Date}
import scala.concurrent.{ExecutionContext, Future, Await}
import scala.concurrent.duration.Duration

class I{
  private var i:Int = 0
  def inc() = i+=1
  def value = i
}

trait Test {
  def doSomething():Unit
  def initialize(i:I):Unit
  def result:Int
}

case class TestLocks() extends Test{
  var ref:I = null

  val lock = new ReentrantLock
  val refInitialized = lock.newCondition()

  def doSomething(){
    lock.lock()
    try {
      if(ref==null) { refInitialized.await() }
      ref.inc()
    }
    finally {
      lock.unlock()
    }
  }

  def initialize(i:I){
    lock.lock()
    try{
      ref = i
      refInitialized.signal()
    }
    finally {
      lock.unlock()
    }
  }

  def result = ref.value
}

case class TestPromises() extends Test{
  val iPromise = concurrent.promise[I]
  def doSomething(){
    val i = Await.result(iPromise.future,Duration.Inf)
    i.inc()
  }

  def initialize(i:I){
    iPromise.success(i)
  }

  def result = Await.result(iPromise.future,Duration.Inf).value
}


object TestRunner{
  def apply(test:Test):Long = {

    val initializationTimeout = 10
    val timer = new Timer()
    timer.schedule(new TimerTask {
      def run(){
        test.initialize(new I)
      }
    },initializationTimeout)

    val start = new Date().getTime

    1 to 1000000 foreach (i=&gt;{
      test.doSomething()
    })
    val end = new Date().getTime

    val duration = end-start-initializationTimeout
//    Console.println(test+" result: "+test.result+" in: "+duration+"ms")
    duration
  }
}

object Tests {
  def run() {

    def average(l: =&gt; Long) =
    {
      val vals = 1 to 100 map(_=&gt;{l.toDouble})
      vals.sum/vals.length
    }

    def averageAsync(l: =&gt; Long) =
    {
      import ExecutionContext.Implicits.global
      val futs = 1 to 100 map(_=&gt;{Future{l.toDouble}})
      val valsFut = Future.sequence(futs)
      val vals = Await.result(valsFut,Duration.Inf)
      vals.sum/vals.length
    }

    Console.println("Locks: "+average(TestRunner(TestLocks()))+"ms")
    Console.println("Promises: "+average(TestRunner(TestPromises()))+"ms")

    Console.println("A Locks: "+averageAsync(TestRunner(TestLocks()))+"ms")
    Console.println("A Promises: "+averageAsync(TestRunner(TestPromises()))+"ms")
  }
}


which outputs:


  Locks: 28.0ms
  Promises: 68.5ms
  A Locks: 49.87ms
  A Promises: 2307.84ms  


what indicates that I have to use locks in "hot zones" and now I want to ensure if those tests are correct. Or maybe I should handle this "wait if uninitialized" case in any other way?
A completely different approach to your answer is a concept called Actors.

Rather than having multiple threads, and having these threads await each other, Actors are like tiny little processes that communicate with each other by sending messages. When you're done with a piece of work, you can send a message to another actor, telling it to go and do something else. 

The Actor Model as it's known is both highly performant and simple to reason about.

Scala is fortunate enough to have an incredible implementation of the Actor Model known as Akka. 

Akka allows you to very simply build large and complex systems - it can even handle distribution across many machines!

Here's a really simple example from the Akka website:

case class Greeting(who: String)

class GreetingActor extends Actor with ActorLogging {
  def receive = {
    case Greeting(who) ⇒ log.info("Hello " + who)
  }
}

val system = ActorSystem("MySystem")
val greeter = system.actorOf(Props[GreetingActor], name = "greeter")
greeter ! Greeting("Charlie Parker")


How easy is that? :-)

I strongly recommend using the Actor Model instead of using conventional threads and locks. Scala provides us with an incredibly powerful toolkit, I encourage you to use it!