Beautiful Concurrency > Conclusion

24.5. Conclusion

My main goal is to persuade you that you can write programs in a fundamentally more modular way using STM than you can with locks and condition variables. First, though, note that transactional memory allows us to completely avoid many of the standard problems that plague lock-based concurrent programs (as explained earlier in the section "Locks Are Bad"). None of these problems arises in STM Haskell. The type system prevents you from reading or writing a TVar outside an atomic block, and because there are no programmer-visible locks, the questions of which locks to take, and in which order, simply do not arise. Other benefits of STM, which I lack the space to describe here, include freedom from lost wakeups and the treatment of exceptions and error recovery.

However, as we also discussed in the section "Locks Are Bad," the worst problem with lock-based programming is that locks do not compose. In contrast, any function with an STM type in Haskell can be composed, using sequencing or choice, with any other function with an STM type to make a new function of STM type. Furthermore, the compound function will guarantee all the same atomicity properties that the individual functions did. In particular, blocking (retry) and choice (orElse), which are fundamentally non-modular when expressed using locks, are fully modular in STM. For example, consider this transaction, which uses functions we defined in the section "Blocking and Choice":

	atomically (do { limitedWithdraw a1 10
	               ; limitedWithdraw2 a2 a3 20 })

This transaction blocks until a1 contains at least 10 units, and either a2 or a3 has 20 units. However, that complicated blocking condition is not written explicitly by the programmer, and indeed if the limitedWithdraw functions are implemented in a sophisticated library, the programmer might have no idea what their blocking conditions are. STM is modular: small programs can be glued together to make larger programs without exposing their implementations.

There are many aspects of transactional memory that I have not covered in this brief overview, including important topics such as nested transactions, exceptions, progress, starvation, and invariants. You can find many of them discussed in papers about STM Haskell.[*****]

[*****] Tim Harris, Simon Marlow, Simon Peyton Jones, and Maurice Herlihy, "Composable memory transactions," ACM Symposium on Principles and Practice of Parallel Programming (PPoPP '05), June 2005; Tim Harris and Simon Peyton Jones, "Transactional memory with data invariants," First ACM SIGPLAN Workshop on Languages, Compilers, and Hardware Support for Transactional Computing (TRANSACT '06), Ottawa, June 2006, ACM; Anthony Discolo, Tim Harris, Simon Marlow, Simon Peyton Jones, and Satnam Singh, "Lock-free data structures using STMs in Haskell," Eighth International Symposium on Functional and Logic Programming (FLOPS '06), April 2006.

Transactional memory is a particularly good "fit" for Haskell. In STM, the implementation potentially must track every memory load and store, but a Haskell STM need only track TVar operations, and these form only a tiny fraction of all the memory loads and stores executed by a Haskell program. Furthermore, the treatment of actions as first-class values, and the rich type system, allow us to offer strong static guarantees without extending the language in any way. However, there is nothing to stop the adoption of transactional memory in mainstream imperative languages, although it may be less elegant and require more language support. Indeed doing so is a hot research topic; Larus and Rajwar give a comprehensive summary.[daggerdaggerdaggerdaggerdagger]

[daggerdaggerdaggerdaggerdagger] James Larus and Ravi Rajwar, Transactional Memory, Morgan & Claypool, 2006.

Using STM is like using a high-level language instead of assembly code—you can still write buggy programs, but many tricky bugs simply cannot occur, and it is much easier to focus attention on the higher-level aspects of the program. There is, alas, no silver bullet that will make concurrent programs easy to write. But STM looks like a promising step forward, and one that will help you to write beautiful code.