Testing Promises vs Lock performance
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!