The free lunch is over – Developing Concurrent Software Ricardo Herrmann (ricardo.herrmann@br.ibm.com)  Thadeu Carmo ( [em...
<ul><li>In the last 3 decades we saw the clocks of processors being increased. </li></ul><ul><li>Our programs got 'faster'...
“The free lunch is over!” [Sutter, 2005] <ul><li>With multi-core processors, programs written in sequential model will no ...
Task parallelism and concurrency <ul><li>Ubiquitous multicore chips imply  parallel programming  is  essential </li></ul><...
The canonical example <ul><li>class Account { </li></ul><ul><li>private int balance; </li></ul><ul><li>synchronized  void ...
Trying to reuse synchronization mechanism <ul><li>class Account { </li></ul><ul><li>private int balance; </li></ul><ul><li...
Adding explicit locking <ul><li>class Account { </li></ul><ul><li>private int balance; </li></ul><ul><li>synchronized void...
Acquiring locks in predefined order <ul><li>class Account { </li></ul><ul><li>private int balance; </li></ul><ul><li>synch...
Problems associated with locks <ul><li>Taking too few locks </li></ul><ul><ul><li>Easy to forget to take a lock </li></ul>...
Why locks are not the answer <ul><li>Large scale software is built by  composition  of smaller components </li></ul><ul><l...
Software Transactional Memory [Shavit, 1995] <ul><li>Key idea: to treat  shared memory  as if it was a  transactional data...
STM Haskell's key operations  [Harris et al., 2005] <ul><li>Atomic blocks </li></ul><ul><ul><li>atomically ::  STM a ->   ...
Account transfer, revisited (STM Haskell) <ul><li>type Account = TVar Int </li></ul><ul><li>transfer ::  Account -> Accoun...
Composable transactional functions <ul><li>limitedWithdraw ::  Account -> Int ->   STM () </li></ul><ul><li>limitedWithdra...
What about side-effects in transactions ? <ul><li>atomically $ do </li></ul><ul><li>x <- readTVar xv </li></ul><ul><li>y <...
Side-effects caused by impure computations in Haskell <ul><li>atomically $ do </li></ul><ul><li>x <- readTVar xv </li></ul...
YES!
OK, theory looks good, but what about practice ? <ul><li>“Is Transactional Programming Actually Easier?” [Rossbach et al.,...
There are no silver bullets <ul><li>Potential problems with STM </li></ul><ul><ul><li>High contention (many transaction co...
Actors Model [Hewitt, 1973] – Asynchronous Messages  <ul><li>A high-level abstraction to write concurrent and distributed ...
Actors in Erlang [Armstrong, 97] <ul><li>Erlang is a functional, dynamically typed language, which runs on top of the an E...
Execution 0 1 1 0 start New actor identified by  counter and initial behavior with value  0  for  current Message  next  i...
Counter Example* <ul><li>* Inspired by the example published in Programming Erlang book </li></ul>start() ->  register( co...
Where is the lock? <ul><li>This example is simple and a similar result can be achieved with a lock based approach </li></u...
Atomicity with Actors [Agha, 1986] <ul><li>Atomicity is possible in the Actors model using of receptionists actors </li></...
Usage Scenarios for Actors <ul><li>Any scenario where you need to distribute independent computation is a suitable scenari...
FYI: Actors, STM in Scala and Java with Akka <ul><li>Scala is a functional and object oriented language that runs on top o...
Counter Actor in Scala with Akka class Counter extends Actor { private var  counter  =  0 def  receive  = {   case  &quot;...
References <ul><li>Hewitt, 1973 -  http://carlhewitt.info/ </li></ul><ul><li>Agha, 1986 - Gul Agha, Actors: a model of con...
 
Upcoming SlideShare
Loading in …5
×

The free lunch is over

2,076 views

Published on

IBM 2010 Brazilian Software Lab Tech Day

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,076
On SlideShare
0
From Embeds
0
Number of Embeds
28
Actions
Shares
0
Downloads
20
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

The free lunch is over

  1. 1. The free lunch is over – Developing Concurrent Software Ricardo Herrmann (ricardo.herrmann@br.ibm.com) Thadeu Carmo ( [email_address] )
  2. 2. <ul><li>In the last 3 decades we saw the clocks of processors being increased. </li></ul><ul><li>Our programs got 'faster' as a consequence of faster processors and other hardware improvements, such as memory access speed and caches </li></ul><ul><li>But have you ever seen commercial single core CPUs with a 10 GHz clock? </li></ul>Where the concurrency crisis began Source: http://www.gotw.ca/publications/concurrency-ddj.htm The “free lunch” ends here
  3. 3. “The free lunch is over!” [Sutter, 2005] <ul><li>With multi-core processors, programs written in sequential model will no longer surf on the wave of this generation of processors </li></ul><ul><ul><li>Even though they get a little bit faster, they won't enjoy the whole improvements </li></ul></ul><ul><li>To surf in the new wave, programs need to be well-written parallel </li></ul><ul><ul><li>Remember: Not all problems can be parallelized (regular parallelism) </li></ul></ul><ul><li>“programming languages and systems will increasingly be forced to deal well with concurrency” </li></ul><ul><ul><li>Java has included support for concurrency since its beginning, but... </li></ul></ul><ul><ul><li>... Java 5.0 includes as part of the release the java.concurrent api, a tentative to improve the support to write concurrent programs </li></ul></ul><ul><ul><li>ISO C++ does not have support to write multithread systems </li></ul></ul><ul><ul><ul><li>Although there are non-standard and non-portable alternatives such as Pthreads and OpenMP </li></ul></ul></ul><ul><li>Fine-grained control constructs (e.g.: loops) are difficult to parallelize </li></ul><ul><ul><li>Functional languages are naturally suited to concurrency due to its nature: </li></ul></ul><ul><ul><ul><li>Immutable object instances, higher order functions, and parallelism exposed in the level of procedure calls </li></ul></ul></ul>
  4. 4. Task parallelism and concurrency <ul><li>Ubiquitous multicore chips imply parallel programming is essential </li></ul><ul><ul><li>So is the need to control access to shared resources </li></ul></ul><ul><li>Dominating paradigm for heterogeneous parallelism: task parallelism </li></ul><ul><ul><li>Explicit threads </li></ul></ul><ul><ul><li>Synchronization can be achieved by means of locks </li></ul></ul><ul><li>And after 30 years of research , the coordination mechanism for shared-memory task-level concurrency of choice is … ? </li></ul>Locks and condition variables * * [Jones, 2010]
  5. 5. The canonical example <ul><li>class Account { </li></ul><ul><li>private int balance; </li></ul><ul><li>synchronized void withdraw(int n) { </li></ul><ul><li>balance = balance - n; </li></ul><ul><li>} </li></ul><ul><li>void deposit(int n) { </li></ul><ul><li>withdraw(-n); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>Synchronization here avoids missing decrements Implicitly synchronized
  6. 6. Trying to reuse synchronization mechanism <ul><li>class Account { </li></ul><ul><li>private int balance; </li></ul><ul><li>synchronized void withdraw(int n) { </li></ul><ul><li>balance = balance - n; </li></ul><ul><li>} </li></ul><ul><li>void deposit(int n) { </li></ul><ul><li>withdraw(-n); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>void transfer(Account from, Account to, int amount) { </li></ul><ul><li>from.withdraw(amount); </li></ul><ul><li>to.deposit(amount); </li></ul><ul><li>} </li></ul>WRONG! Intermediate state here Another thread sees money is absent from both accounts
  7. 7. Adding explicit locking <ul><li>class Account { </li></ul><ul><li>private int balance; </li></ul><ul><li>synchronized void withdraw(int n) { </li></ul><ul><li>balance = balance - n; </li></ul><ul><li>} </li></ul><ul><li>void deposit(int n) { </li></ul><ul><li>withdraw(-n); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>void transfer(Account from, Account to, int amount) { </li></ul><ul><li>from.lock(); to.lock(); </li></ul><ul><li>from.withdraw(amount); </li></ul><ul><li>to.deposit(amount); </li></ul><ul><li>from.unlock(); to.unlock(); </li></ul><ul><li>} </li></ul>Thread 1 transfer( ac1 , ac2 ,10) ac1 .lock() ac2 .lock() ... Thread 2 transfer( ac2 , ac1 ,20) ac2 .lock() ac1 .lock() ... WRONG! Deadlock
  8. 8. Acquiring locks in predefined order <ul><li>class Account { </li></ul><ul><li>private int balance; </li></ul><ul><li>synchronized void withdraw(int n) { </li></ul><ul><li>balance = balance - n; </li></ul><ul><li>} </li></ul><ul><li>void deposit(int n) { </li></ul><ul><li>withdraw(-n); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>void transfer(Account from, Account to, int amount) { </li></ul><ul><li>if (from < to) { from.lock(); to.lock(); } </li></ul><ul><li>else { to.lock(); from.lock(); } </li></ul><ul><li>from.withdraw(amount); </li></ul><ul><li>to.deposit(amount); </li></ul><ul><li>if (from < to) { from.unlock(); to.unlock(); } </li></ul><ul><li>else { to.unlock(); from.unlock(); } </li></ul><ul><li>} </li></ul>Works if the full set of locks can be predicted in advance <ul><li>But what if: </li></ul><ul><li>We wish to block until there's enough funds ? </li></ul><ul><li>If it's not enough, transfer from another account ? </li></ul>Damn, this is hard ...
  9. 9. Problems associated with locks <ul><li>Taking too few locks </li></ul><ul><ul><li>Easy to forget to take a lock </li></ul></ul><ul><ul><li>Causes race conditions, which are hard to debug </li></ul></ul><ul><li>Taking too many locks </li></ul><ul><ul><li>Easy to take too many locks and: </li></ul></ul><ul><ul><ul><li>inhibit concurrency (at best) </li></ul></ul></ul><ul><ul><ul><li>cause deadlock (at worst) </li></ul></ul></ul><ul><li>Taking the wrong locks </li></ul><ul><ul><li>Connection between lock and data it protects is just an implicit convention </li></ul></ul><ul><li>Taking locks in the wrong order </li></ul><ul><ul><li>To avoid deadlock, the locking protocol requires locks to be acquired in a certain order </li></ul></ul><ul><li>Error recovery </li></ul><ul><ul><li>In face of an error, it's hard for the programmer to guarantee that: </li></ul></ul><ul><ul><ul><li>no error can leave the system in an inconsistent state </li></ul></ul></ul><ul><ul><ul><li>locks are not held indefinitely </li></ul></ul></ul><ul><ul><li>Need to restore invariants and release locks in exception handlers (can get very complicated) </li></ul></ul><ul><li>Lost wake-ups and erroneous entries </li></ul><ul><ul><li>Easy to forget to signal a condition variable </li></ul></ul><ul><ul><li>Easy to forget to re-test a condition after wake-up </li></ul></ul>
  10. 10. Why locks are not the answer <ul><li>Large scale software is built by composition of smaller components </li></ul><ul><li>Locks and condition variables do not compose </li></ul><ul><li>So, locks and condition variables do not support modular programming </li></ul><ul><li>In the Accounts example: </li></ul><ul><ul><li>Correct fragments may fail when combined </li></ul></ul><ul><ul><li>Individually correct operations (deposit, withdraw) cannot be composed into larger correct operations </li></ul></ul>
  11. 11. Software Transactional Memory [Shavit, 1995] <ul><li>Key idea: to treat shared memory as if it was a transactional database </li></ul><ul><li>Original idea: hardware for transactions [Knight, 1986] (paper and patent) </li></ul><ul><li>Based on atomic blocks : atomic { ... sequential code ... } </li></ul><ul><ul><li>Atomicity: </li></ul></ul><ul><ul><ul><li>All-or-nothing semantics </li></ul></ul></ul><ul><ul><ul><li>No other thread can see a partial state </li></ul></ul></ul><ul><ul><li>Isolation: </li></ul></ul><ul><ul><ul><li>Threads operate completely unaffected by other threads </li></ul></ul></ul><ul><ul><ul><li>As if threads work on individual snapshots of the world </li></ul></ul></ul><ul><li>Cannot deadlock (there are no locks) </li></ul><ul><li>STM operations are composable [Harris et al, 2005] </li></ul><ul><li>More easily realized in a purely functional language like Haskell </li></ul>
  12. 12. STM Haskell's key operations [Harris et al., 2005] <ul><li>Atomic blocks </li></ul><ul><ul><li>atomically :: STM a -> IO a </li></ul></ul><ul><li>Blocking and choice </li></ul><ul><ul><li>retry :: STM a </li></ul></ul><ul><ul><li>orElse :: STM a -> STM a -> STM a </li></ul></ul><ul><li>Transactional variables </li></ul><ul><ul><li>newTVar :: a -> STM (TVar a) </li></ul></ul><ul><ul><li>readTVar :: TVar a -> STM a </li></ul></ul><ul><ul><li>writeTVar :: TVar a -> a -> STM () </li></ul></ul>The outermost monad (“computational context”), where I/O is possible Inner monad, where only transactional variable changes are possible Only functions “inside” STM can only be evaluated in the STM monad (compiler error otherwise). No I/O possible
  13. 13. Account transfer, revisited (STM Haskell) <ul><li>type Account = TVar Int </li></ul><ul><li>transfer :: Account -> Account -> Int -> IO () </li></ul><ul><li>transfer from to amount = </li></ul><ul><li>atomically $ do </li></ul><ul><li>deposit to amount </li></ul><ul><li>withdraw from amount </li></ul><ul><li>withdraw :: Account -> Int -> STM () </li></ul><ul><li>withdraw acc amount = do </li></ul><ul><li>bal <- readTVar acc </li></ul><ul><li>writeTVar acc (bal – amount) </li></ul><ul><li>deposit :: Account -> Int -> STM () </li></ul><ul><li>deposit acc amount = withdraw acc (- amount) </li></ul><ul><li>But what if: </li></ul><ul><li>We wish to block until there's enough funds ? </li></ul><ul><li>If it's not enough, transfer from another account ? </li></ul>
  14. 14. Composable transactional functions <ul><li>limitedWithdraw :: Account -> Int -> STM () </li></ul><ul><li>limitedWithdraw acc amount = do </li></ul><ul><li>bal <- readTVar acc </li></ul><ul><li>if amount > 0 && amount > bal </li></ul><ul><li>then retry </li></ul><ul><li>else writeTVar acc (bal – amount) </li></ul><ul><li>limitedWithdraw2 :: Account -> Account -> Int -> STM () </li></ul><ul><li>limitedWithdraw2 ac1 ac2 amt = </li></ul><ul><li>orElse (limitedWithdraw ac1 amt) (limitedWithdraw ac2 amt) </li></ul><ul><li>Semantics of ( orElse a1 a2 ): </li></ul><ul><li>Perform a1 </li></ul><ul><li>If a1 retries (i.e. calls retry ), try a2 </li></ul><ul><li>If a2 also retries, the whole action retries. </li></ul><ul><li>If retry is evaluated: </li></ul><ul><li>Transaction is abandoned </li></ul><ul><li>Retried at a later time </li></ul><ul><ul><li>When acc is changed (for efficiency) </li></ul></ul><ul><ul><li>STM knows this because acc is in the read log </li></ul></ul>
  15. 15. What about side-effects in transactions ? <ul><li>atomically $ do </li></ul><ul><li>x <- readTVar xv </li></ul><ul><li>y <- readTVar yv </li></ul><ul><li>if x > y then launchMissiles </li></ul><ul><li>else return () </li></ul><ul><li>launchMissiles </li></ul>Causes irreversible international side-effects
  16. 16. Side-effects caused by impure computations in Haskell <ul><li>atomically $ do </li></ul><ul><li>x <- readTVar xv </li></ul><ul><li>y <- readTVar yv </li></ul><ul><li>if x > y then launchMissiles </li></ul><ul><li>else return () </li></ul><ul><li>However, launchMissiles :: IO () </li></ul><ul><li><interactive>:1:82: </li></ul><ul><li>Couldn't match expected type `STM a' against inferred type `IO ()' </li></ul><ul><li>In the expression: launchMissiles </li></ul><ul><li>In the expression: if x > y then launchMissiles else return () </li></ul><ul><li>In the second argument of `($)', namely </li></ul><ul><li>`do { x <- readTVar xv; </li></ul><ul><li>y <- readTVar yv; </li></ul><ul><li>if x > y then launchMissiles else return () }' </li></ul>Too easy to be true ? Does it work ?
  17. 17. YES!
  18. 18. OK, theory looks good, but what about practice ? <ul><li>“Is Transactional Programming Actually Easier?” [Rossbach et al., 2010] </li></ul><ul><ul><li>237 undergraduate students, 1323 parallel programs in total </li></ul></ul><ul><ul><li>Task: to implement the same programs using: </li></ul></ul><ul><ul><ul><li>Coarse and fine-grain locks </li></ul></ul></ul><ul><ul><ul><li>Monitors </li></ul></ul></ul><ul><ul><ul><li>Transactions </li></ul></ul></ul><ul><li>Inexperienced programmers found syntax to be an entry barrier for transactional programming </li></ul><ul><li>Students found transactions to be: </li></ul><ul><ul><li>harder to use than coarse-grain locks </li></ul></ul><ul><ul><li>slightly easier to use than fine-grained locks </li></ul></ul><ul><li>But … overwhelmingly, the number and types of programming errors the students made was much lower for transactions than for locks. </li></ul><ul><li>On a similar programming problem, over 70% of students made errors with fine-grained locking, while less than 10% made errors with transactions </li></ul>
  19. 19. There are no silver bullets <ul><li>Potential problems with STM </li></ul><ul><ul><li>High contention (many transaction collisions) can lead to: </li></ul></ul><ul><ul><ul><li>Potential bad performance and too high latency </li></ul></ul></ul><ul><li>For STM to work well, you need: </li></ul><ul><ul><li>Very limited side effects in the computational fabric </li></ul></ul><ul><ul><ul><li>None in STM Haskell, unsafe effects in other languages </li></ul></ul></ul><ul><ul><li>Limited communication between threads </li></ul></ul><ul><ul><ul><li>In STM Haskell, transactions “communicate” by committing to the heap </li></ul></ul></ul><ul><ul><li>A “simple design” </li></ul></ul><ul><ul><ul><li>For example, some occasional data structures are: </li></ul></ul></ul><ul><ul><ul><ul><li>Necessarily shared </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Necessarily hot-spots </li></ul></ul></ul></ul><ul><ul><ul><li>In this case, STM is not the best solution </li></ul></ul></ul><ul><li>“ Concurrency is too complex to be slain with one bullet” [Simon P. Jones] </li></ul>
  20. 20. Actors Model [Hewitt, 1973] – Asynchronous Messages <ul><li>A high-level abstraction to write concurrent and distributed systems </li></ul><ul><li>Frees the developer from having to deal with explicit locking and thread management </li></ul><ul><li>Shares 'nothing' – Asynchronous message exchange </li></ul><ul><li>Formal Definition [Agha, 1986] – An actor is... </li></ul><ul><ul><li>A computational agent which defines: </li></ul></ul><ul><ul><ul><li>its mailbox </li></ul></ul></ul><ul><ul><ul><li>its behavior </li></ul></ul></ul><ul><ul><li>And which maps each incoming communication into a 3-tuple consisting of: </li></ul></ul><ul><ul><ul><li>A finite set of communications sent to other actors </li></ul></ul></ul><ul><ul><ul><li>A new behavior to be used when processing future communications </li></ul></ul></ul><ul><ul><ul><li>A finite set of newly created actors </li></ul></ul></ul><ul><ul><li>A communication is a 3-tuple consisting of: </li></ul></ul><ul><ul><ul><li>An unique id </li></ul></ul></ul><ul><ul><ul><li>The target mailbox </li></ul></ul></ul><ul><ul><ul><li>Information the actor will proceed </li></ul></ul></ul>
  21. 21. Actors in Erlang [Armstrong, 97] <ul><li>Erlang is a functional, dynamically typed language, which runs on top of the an Erlang virtual machine. </li></ul><ul><li>It is designed for programming concurrent, large-scale, and distributed real-time software. </li></ul><ul><li>Actors in Erlang are: </li></ul><ul><ul><li>Ultra lightweight process created inside the Erlang VM </li></ul></ul><ul><ul><ul><li>Each actor's header uses only ~400 bytes of memory </li></ul></ul></ul><ul><ul><ul><li>There is no shared memory among them – the only possible way of interaction is sending messages </li></ul></ul></ul><ul><li>Existing primitives in the language to work with Actors </li></ul><ul><ul><li>send (!) : used to send a message – actor ! {myaddress, value} </li></ul></ul><ul><ul><li>spawn: used to spawn children actors </li></ul></ul><ul><ul><li>receive: used to define the block to receive communications </li></ul></ul>
  22. 22. Execution 0 1 1 0 start New actor identified by counter and initial behavior with value 0 for current Message next in this actor mailbox. new behavior defines value 1 for current Message reset in this actor mailbox. new behavior. value 0 for current Message current in this actor mailbox. no new behavior. value 1 for current
  23. 23. Counter Example* <ul><li>* Inspired by the example published in Programming Erlang book </li></ul>start() -> register( counter , spawn ( fun() -> counter ( 0 ) end) ). counter ( N ) -> receive {From, next } -> From ! { ok , N + 1 }, counter ( N+1 ); {From, current } -> From ! { ok , N }, counter ( N ); {From, reset } -> From ! { ok , 0 }, counter ( 0 ) end . next() -> rpc( next ). reset() -> rpc( reset ). current() -> rpc( current ). rpc(Request) -> counter ! {self(), Request}, receive Response -> Response end .
  24. 24. Where is the lock? <ul><li>This example is simple and a similar result can be achieved with a lock based approach </li></ul><ul><li>Some of the Actor's characteristics: </li></ul><ul><ul><li>No explicit lock </li></ul></ul><ul><ul><li>This model has the composability property </li></ul></ul><ul><ul><ul><li>You can compose modules without the need to know details of APIs you want to compose </li></ul></ul></ul><ul><ul><li>This model has the atomicity property </li></ul></ul><ul><ul><ul><li>You can create atomic transactions with no pre-defined level of granularity – it is up to the programmer define that. </li></ul></ul></ul><ul><ul><li>Spawn on remote nodes are allowed – Scalability and Performance becomes simpler </li></ul></ul><ul><ul><li>You can define a supervisor hierarchy linking process </li></ul></ul><ul><ul><li>There are idioms you can use to be notified a child process has died, and define restart policies – Availability becomes simpler </li></ul></ul><ul><ul><li>The model (and consequently the languages that implements it) was created for concurrent and parallel executions, you are not adapting general usage languages! </li></ul></ul><ul><ul><li>The linearity of the code is 'lost' </li></ul></ul><ul><ul><li>There is no global order of the events, but just a partial order (in the graph component of the actors) </li></ul></ul><ul><ul><li>Testability becomes more complex </li></ul></ul>
  25. 25. Atomicity with Actors [Agha, 1986] <ul><li>Atomicity is possible in the Actors model using of receptionists actors </li></ul>receptionist account ricardo 1000.0 {transfer, account_ricardo, account_thadeu, 250.0} {withdraw, 250.0} account ricardo 750.0 {deposit, 250.0} {withdraw_ok, 750.0} account thadeu 0.0 account thadeu 250.0 {deposit_ok, 250.0} {transfer_ok}
  26. 26. Usage Scenarios for Actors <ul><li>Any scenario where you need to distribute independent computation is a suitable scenario: </li></ul><ul><ul><li>Parallelizing sequential code </li></ul></ul><ul><ul><ul><li>Granularity of concurrency – small messages and BIG COMPUTATIONS </li></ul></ul></ul><ul><ul><li>Map/Reduce </li></ul></ul><ul><ul><ul><li>Reduce process takes the input and chops it into small sub-problems, distributing those to mapping process </li></ul></ul></ul><ul><ul><ul><li>Mapping process do the processing and produce and passes the answer back to the reduce process </li></ul></ul></ul><ul><ul><ul><li>Reduce process combine the results received from the mapping processes to get the result of the original problem </li></ul></ul></ul><ul><ul><li>Web servers </li></ul></ul><ul><ul><ul><li>In Yaws [Yaws, 2002], an actor is created to handle each client </li></ul></ul></ul><ul><ul><ul><li>In Lift [Lift], for each created web session, an actor is created. All HTTP requests are forwarded to the session actor. It is easier to build Ajax/Comet apps, as you can abstract out the HTTP requests from the time of rendering. </li></ul></ul></ul>
  27. 27. FYI: Actors, STM in Scala and Java with Akka <ul><li>Scala is a functional and object oriented language that runs on top of JVM </li></ul><ul><li>Scala has its own Actors Model implementation </li></ul><ul><li>Akka is an open source project which is an alternative implementation of both STM and Actors Model </li></ul><ul><li>It has both Java API and Scala API </li></ul><ul><li>The Actor implementation is inspired on the Erlang OTP platform </li></ul><ul><li>Actors are subclass of the Actor class and need to define the receive method, which is a partial function </li></ul>
  28. 28. Counter Actor in Scala with Akka class Counter extends Actor { private var counter = 0 def receive = { case &quot;Reset&quot; => counter = 0 self.reply( counter ) case &quot;Next&quot; => counter = counter + 1 self.reply( counter ) case &quot;Current&quot; => self.reply( counter ) } }
  29. 29. References <ul><li>Hewitt, 1973 - http://carlhewitt.info/ </li></ul><ul><li>Agha, 1986 - Gul Agha, Actors: a model of concurrent computation in distributed systems, MIT Press, Cambridge, MA, 1986 </li></ul><ul><li>Sutter, 2005 - http://www.gotw.ca/publications/concurrency-ddj.htm </li></ul><ul><li>Armstrong, 97 - Armstrong Joe, The development of Erlang, ICFP '97: Proceedings of the second ACM SIGPLAN international conference on Functional programming </li></ul><ul><li>Akka - http://www.akkasource.org </li></ul><ul><li>Yaws - http://yaws.hyber.org </li></ul><ul><li>Lift - http://liftweb.net </li></ul><ul><li>Jones, Simon 2007- Beautiful Concurrency - http://research.microsoft.com/en-us/um/people/simonpj/papers/stm/beautiful.pdf </li></ul><ul><li>Boner, Jonas 2009 - State, You’re Doing It Wrong: Exploring Alternative Concurrency Paradigms on the JVM </li></ul>

×