Now that most computers have multiple cores, there is a lot of interest in finding elegant ways to write multicore/multithreaded code. One popular approach is to use functional data structures along with a software transactional memory system.
Using software transactional memory, you can share complex data structures between several threads, with a guarantee that no thread will see inconsistent information in the data, even if it tries to read shared data while another thread is attempting to write to it.
Multithreaded code tends to be very buggy. By using software transactional memory, you can greatly increase your odds of writing bug-free multithreaded software.
In this example, we define two bank accounts called checking
and savings
, with a total amount of $300 between them. We then define a transfer-to-savings
function, which can be called to move money from the checking
account to the savings
account .
Example A-10. Example
(def checking (ref 100)) (def savings (ref 200)) (defn transfer-to-savings [n] (dosync (alter checking - n) (alter savings + n)))
This example is in the Clojure Lisp dialect and won’t run in Common Lisp.
Because this function contains a dosync
block, Clojure will make sure these two alter
operations happen at the same moment in time. Of course, both values aren’t really altered at the exact same point in time, but the language makes sure it will appear to happen simultaneously. If another thread were to read these two accounts at the same time, also within a dosync
block, it would see exactly $300 in the combined accounts, no matter how many times either thread checks these values.
3.140.195.225