Transactional Memory (TM) programming really has two elements that need to be discussed: productivity and performance.
Compared to locks, Transactional Memory can be considered a higher-level access-control construct. The difference is akin to imperative programming vs declarative.
From a programmer's standpoint, TM is supposed to allow you to declare what needs to be executed atomically, rather than providing instructions (in the forms of locking code) on how the atomic execution should be done.
This comes with a number of promised benefits compared to locking -- easier reasoning, composability, deadlock-freedom.
Compared to locks, TM is (supposed to be --- implementations can vary here!) an optimistic access-control construct, as opposed to the pessimism of locks. The general idea of TM is that instead of requiring mutual exclusion from an atomic region, as you would with locks, the system allows multiple threads to enter the atomic region.
By tracking the state changes, and monitoring for the possibility of data races, in the case where a race does not occur, the system will allow the threads to commit. Otherwise, at least one transaction will be aborted and re-started. In the case where conflict is rare, this can be a substantial performance gain.
Like all real systems, there's a list of caveats as long as my arm. Here's a partial set:
- In an HTM, you need to worry about transactions which can't be committed --- illegal opcodes, too much state for the system to handle, etc. Which means you need a fallback path.
- How to deal with atomic IO operations?
- Performance goes up if conflict is rare --- but what about if it's not? Performance goes down, by wasting work retrying again and again.
- How do you cooperate between threads using TM instead of locks?