It's not really a matter of locking, it's about what the reference means:
TVar
is a mutable reference within STM
, representing general shared state. You create it holding a value, you can read and write to it, etc. It's very much akin to IORef
or STRef
(which are the same thing anyway).
TMVar
is a reference to a slot that threads can use to communicate. It can be created holding a value, or empty. You can put a value into it, which if already filled blocks until someone else empties it; or you can take a value from it, which if already empty blocks until someone fills it. It's obviously akin to an MVar
, but for many common uses it might be simpler to think of it as a single-element queue used for a communicating producer/consumer pair.
In short, TVar
is general shared state, use it if you want atomic updates to data from arbitrary places. TMVar
is a synchronization primitive, use it if you want a thread to wait until something becomes available, while another waits for something to be needed.
Also note TChan
, which is implemented roughly as two TVar
s holding locations in a linked list where each forward link is also a TVar
, and works as an unbounded queue for communication.
All of these can be used in slightly different ways, of course--you can peek at the value of a TMVar
without removing it, for instance, if you want a scenario where multiple threads all wait for a single resource to become available but it's never "used up".