Skip to content

Commit a5076bf

Browse files
authored
Merge pull request #890 from ruby-concurrency/clarify-opacity
Clarify opacity of TVar in the current implementation
2 parents 63a6907 + c951c33 commit a5076bf

File tree

1 file changed

+69
-3
lines changed

1 file changed

+69
-3
lines changed

docs-source/tvar.md

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,80 @@ We only support strong isolation if you use the API correctly. In order words,
2525
we do not support strong isolation.
2626

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

3230
See:
3331

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

34+
Note that this implementation allows transactions to continue in a zombie state
35+
with inconsistent reads, so it's possible for the marked exception to be raised
36+
in the example below.
37+
38+
```ruby
39+
require 'concurrent-ruby'
40+
41+
v1 = Concurrent::TVar.new(0)
42+
v2 = Concurrent::TVar.new(0)
43+
44+
2.times.map{
45+
Thread.new do
46+
while true
47+
Concurrent::atomically do
48+
t1 = v1.value
49+
t2 = v2.value
50+
raise [t1, t2].inspect if t1 != t2 # detect zombie transactions
51+
end
52+
end
53+
end
54+
55+
Thread.new do
56+
100_000.times do
57+
Concurrent::atomically do
58+
v1.value += 1
59+
v2.value += 1
60+
end
61+
end
62+
end
63+
}.each { |t| p t.join }
64+
```
65+
66+
However, the inconsistent reads are detected correctly at commit time. This
67+
means the script below will always print `[2000000, 200000]`.
68+
69+
```ruby
70+
require 'concurrent-ruby'
71+
72+
v1 = Concurrent::TVar.new(0)
73+
v2 = Concurrent::TVar.new(0)
74+
75+
2.times.map{
76+
Thread.new do
77+
while true
78+
Concurrent::atomically do
79+
t1 = v1.value
80+
t2 = v2.value
81+
end
82+
end
83+
end
84+
85+
Thread.new do
86+
100_000.times do
87+
Concurrent::atomically do
88+
v1.value += 1
89+
v2.value += 1
90+
end
91+
end
92+
end
93+
}.each { |t| p t.join }
94+
95+
p [v1.value, v2.value]
96+
```
97+
98+
This is called a lack of *opacity*. In the future we will look at more advanced
99+
algorithms, contention management and using existing Java implementations when
100+
in JRuby.
101+
36102
## Motivation
37103

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

0 commit comments

Comments
 (0)