Channel Synchronization in Scala

We can use channels to synchronize execution across threads. Here’s an example of using a blocking receive to wait for a thread to finish. When waiting for multiple threads to finish, you may prefer to use a CountDownLatch or Future.

import scala.concurrent.{Future, Await}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

object ChannelSynchronization {
  // This is the function we'll run in a separate thread. The
  // `done` promise will be used to notify another thread
  // that this function's work is done.
  def worker(done: scala.concurrent.Promise[Boolean]): Unit = {
    print("working...")
    Thread.sleep(1000) // Simulate work
    println("done")

    // Complete the promise to notify that we're done.
    done.success(true)
  }

  def main(args: Array[String]): Unit = {
    // Create a promise to be completed when the work is done
    val done = scala.concurrent.Promise[Boolean]()

    // Start a worker thread, giving it the promise to complete
    Future {
      worker(done)
    }

    // Block until we receive a notification from the
    // worker on the Future
    Await.result(done.future, Duration.Inf)
  }
}

To run the program:

$ scala ChannelSynchronization.scala
working...done

If you removed the Await.result(done.future, Duration.Inf) line from this program, the program would exit before the worker even started.

In this Scala version:

  1. We use a Promise and its associated Future instead of a channel. A Promise in Scala is somewhat similar to a single-use channel in Go.

  2. The worker function takes a Promise[Boolean] instead of a channel. It completes the promise when the work is done.

  3. In the main function, we create a Promise and pass it to a new Future that runs the worker.

  4. We use Await.result to block until the Future completes, which is analogous to receiving from a channel in the Go version.

  5. We use Thread.sleep instead of time.Sleep to simulate work being done.

This example demonstrates how to use Scala’s concurrency primitives to achieve similar synchronization behavior to Go’s channels.