23 |
|
* the lock is held. When it is even (i.e., ({@code lock.getSequence() |
24 |
|
* & 1L) == 0L}), the lock is released. Method {@link |
25 |
|
* #awaitAvailability} can be used to await availability of the lock, |
26 |
< |
* returning its current sequence number. Sequence numbers are of type |
27 |
< |
* {@code long} to ensure that they will not wrap around until |
28 |
< |
* hundreds of years of use under current processor rates. A |
29 |
< |
* SequenceLock can be created with a specified number of |
30 |
< |
* spins. Attempts to lock or await release will retry at least the |
31 |
< |
* given number of times before blocking. If not specified, a default, |
32 |
< |
* possibly platform-specific, value is used. |
26 |
> |
* returning its current sequence number. Sequence numbers (as well as |
27 |
> |
* reentrant hold counts) are of type {@code long} to ensure that they |
28 |
> |
* will not wrap around until hundreds of years of use under current |
29 |
> |
* processor rates. A SequenceLock can be created with a specified |
30 |
> |
* number of spins. Attempts to acquire the lock in method {@link |
31 |
> |
* #lock} will retry at least the given number of times before |
32 |
> |
* blocking. If not specified, a default, possibly platform-specific, |
33 |
> |
* value is used. |
34 |
|
* |
35 |
|
* <p>Except for the lack of support for specified fairness policies, |
36 |
|
* or {@link Condition} objects, a SequenceLock can be used in the |
53 |
|
* |
54 |
|
* <pre> {@code |
55 |
|
* class Point { |
56 |
< |
* private float x, y; |
56 |
> |
* private double x, y; |
57 |
|
* private final SequenceLock sl = new SequenceLock(); |
58 |
|
* |
59 |
< |
* void move(float deltaX, float deltaY) { // an exclusively locked method |
59 |
> |
* void move(double deltaX, double deltaY) { // an exclusively locked method |
60 |
|
* sl.lock(); |
61 |
|
* try { |
62 |
|
* x += deltaX; |
66 |
|
* } |
67 |
|
* } |
68 |
|
* |
69 |
< |
* float distanceFromOriginV1() { // A read-only method |
70 |
< |
* float currentX, currentY; |
69 |
> |
* double distanceFromOriginV1() { // A read-only method |
70 |
> |
* double currentX, currentY; |
71 |
|
* long seq; |
72 |
|
* do { |
73 |
|
* seq = sl.awaitAvailability(); |
74 |
|
* currentX = x; |
75 |
|
* currentY = y; |
76 |
|
* } while (sl.getSequence() != seq); // retry if sequence changed |
77 |
< |
* return (float)Math.sqrt(currentX * currentX + currentY * currentY); |
77 |
> |
* return Math.sqrt(currentX * currentX + currentY * currentY); |
78 |
|
* } |
79 |
|
* |
80 |
< |
* float distanceFromOriginV2() { // Uses bounded retries before locking |
81 |
< |
* float currentX, currentY; |
80 |
> |
* double distanceFromOriginV2() { // Uses bounded retries before locking |
81 |
> |
* double currentX, currentY; |
82 |
|
* long seq; |
83 |
|
* int retries = RETRIES_BEFORE_LOCKING; // for example 8 |
84 |
|
* try { |
93 |
|
* if (retries < 0) |
94 |
|
* sl.unlock(); |
95 |
|
* } |
96 |
< |
* return (float)Math.sqrt(currentX * currentX + currentY * currentY); |
96 |
> |
* return Math.sqrt(currentX * currentX + currentY * currentY); |
97 |
|
* } |
98 |
|
*}}</pre> |
99 |
|
* |
112 |
|
/** |
113 |
|
* The number of reentrant holds on this lock. Uses a long for |
114 |
|
* compatibility with other AbstractQueuedLongSynchronizer |
115 |
< |
* operations. |
115 |
> |
* operations. Accessed only by lock holder. |
116 |
|
*/ |
117 |
|
long holds; |
118 |
|
|
186 |
|
|
187 |
|
final long awaitAvailability() { |
188 |
|
long s; |
188 |
– |
int k = spins; |
189 |
|
while (((s = getState()) & 1L) != 0L && |
190 |
|
getExclusiveOwnerThread() != Thread.currentThread()) { |
191 |
< |
if (k > 0) |
192 |
< |
--k; |
193 |
< |
else { |
194 |
< |
acquireShared(1L); |
195 |
< |
releaseShared(1L); |
196 |
< |
} |
191 |
> |
acquireShared(1L); |
192 |
> |
releaseShared(1L); |
193 |
|
} |
194 |
|
return s; |
195 |
|
} |
244 |
|
|
245 |
|
/** |
246 |
|
* Creates an instance of {@code SequenceLock} with the default |
247 |
< |
* number of retry attempts to lock or await release before |
252 |
< |
* blocking. |
247 |
> |
* number of retry attempts to acquire the lock before blocking. |
248 |
|
*/ |
249 |
|
public SequenceLock() { sync = new Sync(DEFAULT_SPINS); } |
250 |
|
|
251 |
|
/** |
252 |
< |
* Creates an instance of {@code SequenceLock} that |
253 |
< |
* will retry attempts to lock or await release |
254 |
< |
* at least the given number times before blocking. |
252 |
> |
* Creates an instance of {@code SequenceLock} that will retry |
253 |
> |
* attempts to acquire the lock at least the given number times |
254 |
> |
* before blocking. |
255 |
|
*/ |
256 |
|
public SequenceLock(int spins) { sync = new Sync(spins); } |
257 |
|
|