1
1
/**
2
- * Copyright 2009-2019 the original author or authors.
2
+ * Copyright 2009-2020 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
15
15
*/
16
16
package org .apache .ibatis .cache .decorators ;
17
17
18
+ import java .text .MessageFormat ;
18
19
import java .util .concurrent .ConcurrentHashMap ;
20
+ import java .util .concurrent .CountDownLatch ;
19
21
import java .util .concurrent .TimeUnit ;
20
- import java .util .concurrent .locks .Lock ;
21
- import java .util .concurrent .locks .ReentrantLock ;
22
22
23
23
import org .apache .ibatis .cache .Cache ;
24
24
import org .apache .ibatis .cache .CacheException ;
@@ -37,7 +37,7 @@ public class BlockingCache implements Cache {
37
37
38
38
private long timeout ;
39
39
private final Cache delegate ;
40
- private final ConcurrentHashMap <Object , ReentrantLock > locks ;
40
+ private final ConcurrentHashMap <Object , CountDownLatch > locks ;
41
41
42
42
public BlockingCache (Cache delegate ) {
43
43
this .delegate = delegate ;
@@ -85,31 +85,35 @@ public void clear() {
85
85
delegate .clear ();
86
86
}
87
87
88
- private ReentrantLock getLockForKey (Object key ) {
89
- return locks .computeIfAbsent (key , k -> new ReentrantLock ());
90
- }
91
-
92
88
private void acquireLock (Object key ) {
93
- Lock lock = getLockForKey (key );
94
- if (timeout > 0 ) {
89
+ CountDownLatch newLatch = new CountDownLatch (1 );
90
+ while (true ) {
91
+ CountDownLatch latch = locks .putIfAbsent (key , newLatch );
92
+ if (latch == null ) {
93
+ break ;
94
+ }
95
95
try {
96
- boolean acquired = lock .tryLock (timeout , TimeUnit .MILLISECONDS );
97
- if (!acquired ) {
98
- throw new CacheException ("Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate .getId ());
96
+ if (timeout > 0 ) {
97
+ boolean acquired = latch .await (timeout , TimeUnit .MILLISECONDS );
98
+ if (!acquired ) {
99
+ throw new CacheException (
100
+ "Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate .getId ());
101
+ }
102
+ } else {
103
+ latch .await ();
99
104
}
100
105
} catch (InterruptedException e ) {
101
106
throw new CacheException ("Got interrupted while trying to acquire lock for key " + key , e );
102
107
}
103
- } else {
104
- lock .lock ();
105
108
}
106
109
}
107
110
108
111
private void releaseLock (Object key ) {
109
- ReentrantLock lock = locks .get (key );
110
- if (lock . isHeldByCurrentThread () ) {
111
- lock .unlock ( );
112
+ CountDownLatch latch = locks .remove (key );
113
+ if (latch == null ) {
114
+ throw new IllegalStateException ( "Detected an attempt at releasing unacquired lock. This should never happen." );
112
115
}
116
+ latch .countDown ();
113
117
}
114
118
115
119
public long getTimeout () {
0 commit comments