ps0604
ps0604

Reputation: 1071

Sequencing futures to avoid race condition

In this example I have a race condition, the string s at the end of the program should print with @ and # replaced:

object TestFutures extends App {

  var s = "THIS IS A STRING"

  val f0 = Future { 0 }
  val f1 = Future { 1 }
  val fx = Seq(f0,f1)

  fx.map { 
    seq => seq.map {  i =>
          println("BEFORE ---> " + s)
          if (i == 0)
              s = s.replace ( "T", "@")
          else
              s = s.replace ("I", "#")
          println("AFTER ---> " + s)
        }
  }


  Thread.sleep(5000)
}

But the code prints

BEFORE ---> THIS IS A STRING
BEFORE ---> THIS IS A STRING
AFTER ---> TH#S #S A STR#NG
AFTER ---> TH#S #S A STR#NG

How to avoid this race condition? how to change the string?

Upvotes: 0

Views: 275

Answers (1)

Dima
Dima

Reputation: 40500

The only sure way to avoid race conditions is to not have mutable state. Something like this would work:

 val s = "THIS IS A STRING"
 Future
   .sequence(Seq(Future(0), Future(1)))
   .map { 
      _.foldLeft(s) {
        case (s, 0) => s.replaceAll("T", "@")
        case (s, _) => s.replaceAll("I", "#")
     }
   }.andThen { 
     case Success(str) => println("RESULT: " + str)
   }

Upvotes: 1

Related Questions