Skip to content

Commit

Permalink
Merge pull request #890 from ruby-concurrency/clarify-opacity
Browse files Browse the repository at this point in the history
Clarify opacity of TVar in the current implementation
  • Loading branch information
pitr-ch authored Oct 11, 2020
2 parents 63a6907 + c951c33 commit a5076bf
Showing 1 changed file with 69 additions and 3 deletions.
72 changes: 69 additions & 3 deletions docs-source/tvar.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,80 @@ We only support strong isolation if you use the API correctly. In order words,
we do not support strong isolation.

Our implementation uses a very simple two-phased locking with versioned locks
algorithm and lazy writes, as per [1]. In the future we will look at more
advanced algorithms, contention management and using existing Java
implementations when in JRuby.
algorithm and lazy writes, as per [1].

See:

1. T. Harris, J. Larus, and R. Rajwar. Transactional Memory. Morgan & Claypool, second edition, 2010.

Note that this implementation allows transactions to continue in a zombie state
with inconsistent reads, so it's possible for the marked exception to be raised
in the example below.

```ruby
require 'concurrent-ruby'

v1 = Concurrent::TVar.new(0)
v2 = Concurrent::TVar.new(0)

2.times.map{
Thread.new do
while true
Concurrent::atomically do
t1 = v1.value
t2 = v2.value
raise [t1, t2].inspect if t1 != t2 # detect zombie transactions
end
end
end

Thread.new do
100_000.times do
Concurrent::atomically do
v1.value += 1
v2.value += 1
end
end
end
}.each { |t| p t.join }
```

However, the inconsistent reads are detected correctly at commit time. This
means the script below will always print `[2000000, 200000]`.

```ruby
require 'concurrent-ruby'

v1 = Concurrent::TVar.new(0)
v2 = Concurrent::TVar.new(0)

2.times.map{
Thread.new do
while true
Concurrent::atomically do
t1 = v1.value
t2 = v2.value
end
end
end

Thread.new do
100_000.times do
Concurrent::atomically do
v1.value += 1
v2.value += 1
end
end
end
}.each { |t| p t.join }

p [v1.value, v2.value]
```

This is called a lack of *opacity*. In the future we will look at more advanced
algorithms, contention management and using existing Java implementations when
in JRuby.

## Motivation

Consider an application that transfers money between bank accounts. We want to
Expand Down

0 comments on commit a5076bf

Please sign in to comment.