Skip to content

Commit cf3a302

Browse files
authored
Remove Synchronized Statements(Loom-friendly) (#173)
Motivation: Synchronized statements tend to pin virtual threads to carrier threads. Modification: Replaced synchronized statements with ReentrantLock Result: Loom-friendly
1 parent d4a9fe0 commit cf3a302

File tree

5 files changed

+72
-26
lines changed

5 files changed

+72
-26
lines changed

src/main/java/io/asyncer/r2dbc/mysql/MySqlConnectionFactory.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.net.InetSocketAddress;
3636
import java.net.SocketAddress;
3737
import java.util.Objects;
38+
import java.util.concurrent.locks.ReentrantLock;
3839
import java.util.function.Predicate;
3940

4041
import static io.asyncer.r2dbc.mysql.internal.util.AssertUtils.requireNonNull;
@@ -157,6 +158,8 @@ private static final class LazyQueryCache {
157158

158159
private final int capacity;
159160

161+
private final ReentrantLock lock = new ReentrantLock();
162+
160163
@Nullable
161164
private volatile QueryCache cache;
162165

@@ -167,11 +170,14 @@ private LazyQueryCache(int capacity) {
167170
public QueryCache get() {
168171
QueryCache cache = this.cache;
169172
if (cache == null) {
170-
synchronized (this) {
173+
lock.lock();
174+
try {
171175
if ((cache = this.cache) == null) {
172176
this.cache = cache = Caches.createQueryCache(capacity);
173177
}
174178
return cache;
179+
} finally {
180+
lock.unlock();
175181
}
176182
}
177183
return cache;

src/main/java/io/asyncer/r2dbc/mysql/cache/PrepareBoundedCache.java

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@
1717
package io.asyncer.r2dbc.mysql.cache;
1818

1919
import java.util.HashMap;
20+
import java.util.concurrent.locks.ReentrantLock;
2021
import java.util.function.IntConsumer;
2122

2223
/**
23-
* A bounded implementation of {@link PrepareCache} that uses synchronized methods to ensure correctness, even
24+
* A bounded implementation of {@link PrepareCache} that uses {@link ReentrantLock} to ensure correctness, even
2425
* it should not be used thread concurrently.
2526
*/
2627
final class PrepareBoundedCache extends HashMap<String, Lru.Node<Integer>> implements PrepareCache {
@@ -33,6 +34,8 @@ final class PrepareBoundedCache extends HashMap<String, Lru.Node<Integer>> imple
3334

3435
private final Lru<Integer> protection;
3536

37+
private final ReentrantLock lock = new ReentrantLock();
38+
3639
PrepareBoundedCache(int capacity) {
3740
int windowSize = Math.max(1, capacity / 100);
3841
int protectionSize = Math.max(1, (int) ((capacity - windowSize) * 0.8));
@@ -45,29 +48,39 @@ final class PrepareBoundedCache extends HashMap<String, Lru.Node<Integer>> imple
4548
}
4649

4750
@Override
48-
public synchronized Integer getIfPresent(String key) {
49-
Lru.Node<Integer> node = super.get(key);
50-
51-
if (node == null) {
52-
return null;
51+
public Integer getIfPresent(String key) {
52+
lock.lock();
53+
try {
54+
Lru.Node<Integer> node = super.get(key);
55+
56+
if (node == null) {
57+
return null;
58+
}
59+
60+
drainRead(node);
61+
return node.getValue();
62+
} finally {
63+
lock.unlock();
5364
}
54-
55-
drainRead(node);
56-
return node.getValue();
5765
}
5866

5967
@Override
60-
public synchronized boolean putIfAbsent(String key, int value, IntConsumer evict) {
61-
Lru.Node<Integer> wantAdd = new Lru.Node<>(key, value);
62-
Lru.Node<Integer> present = super.putIfAbsent(key, wantAdd);
63-
64-
if (present == null) {
65-
drainAdded(wantAdd, evict);
66-
return true;
68+
public boolean putIfAbsent(String key, int value, IntConsumer evict) {
69+
lock.lock();
70+
try {
71+
Lru.Node<Integer> wantAdd = new Lru.Node<>(key, value);
72+
Lru.Node<Integer> present = super.putIfAbsent(key, wantAdd);
73+
74+
if (present == null) {
75+
drainAdded(wantAdd, evict);
76+
return true;
77+
}
78+
79+
drainRead(present);
80+
return false;
81+
} finally {
82+
lock.unlock();
6783
}
68-
69-
drainRead(present);
70-
return false;
7184
}
7285

7386
@Override

src/main/java/io/asyncer/r2dbc/mysql/client/RequestQueue.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.util.Queue;
2323
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
24+
import java.util.concurrent.locks.ReentrantLock;
2425

2526
abstract class LeftPadding {
2627

@@ -57,6 +58,8 @@ final class RequestQueue extends ActiveStatus implements Runnable {
5758

5859
private final Queue<RequestTask<?>> queue = Queues.<RequestTask<?>>small().get();
5960

61+
private final ReentrantLock lock = new ReentrantLock();
62+
6063
@Nullable
6164
private volatile RuntimeException disposed;
6265

@@ -145,14 +148,17 @@ private RuntimeException requireDisposed() {
145148
RuntimeException disposed = this.disposed;
146149

147150
if (disposed == null) {
148-
synchronized (this) {
151+
lock.lock();
152+
try {
149153
disposed = this.disposed;
150154

151155
if (disposed == null) {
152156
this.disposed = disposed = new IllegalStateException("Request queue was disposed");
153157
}
154158

155159
return disposed;
160+
} finally {
161+
lock.unlock();
156162
}
157163
}
158164

src/main/java/io/asyncer/r2dbc/mysql/codec/DefaultCodecs.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.HashMap;
3535
import java.util.List;
3636
import java.util.Map;
37+
import java.util.concurrent.locks.ReentrantLock;
3738

3839
import static io.asyncer.r2dbc.mysql.internal.util.AssertUtils.requireNonNull;
3940

@@ -319,16 +320,19 @@ static final class Builder implements CodecsBuilder {
319320

320321
private final ByteBufAllocator allocator;
321322

322-
@GuardedBy("this")
323+
@GuardedBy("lock")
323324
private final ArrayList<Codec<?>> codecs = new ArrayList<>();
324325

326+
private final ReentrantLock lock = new ReentrantLock();
327+
325328
Builder(ByteBufAllocator allocator) {
326329
this.allocator = allocator;
327330
}
328331

329332
@Override
330333
public CodecsBuilder addFirst(Codec<?> codec) {
331-
synchronized (this) {
334+
lock.lock();
335+
try {
332336
if (codecs.isEmpty()) {
333337
Codec<?>[] defaultCodecs = defaultCodecs(allocator);
334338

@@ -339,24 +343,30 @@ public CodecsBuilder addFirst(Codec<?> codec) {
339343
} else {
340344
codecs.add(0, codec);
341345
}
346+
} finally {
347+
lock.unlock();
342348
}
343349
return this;
344350
}
345351

346352
@Override
347353
public CodecsBuilder addLast(Codec<?> codec) {
348-
synchronized (this) {
354+
lock.lock();
355+
try {
349356
if (codecs.isEmpty()) {
350357
codecs.addAll(InternalArrays.asImmutableList(defaultCodecs(allocator)));
351358
}
352359
codecs.add(codec);
360+
} finally {
361+
lock.unlock();
353362
}
354363
return this;
355364
}
356365

357366
@Override
358367
public Codecs build() {
359-
synchronized (this) {
368+
lock.lock();
369+
try {
360370
try {
361371
if (codecs.isEmpty()) {
362372
return new DefaultCodecs(defaultCodecs(allocator));
@@ -366,6 +376,8 @@ public Codecs build() {
366376
codecs.clear();
367377
codecs.trimToSize();
368378
}
379+
} finally {
380+
lock.unlock();
369381
}
370382
}
371383
}

src/main/java/io/asyncer/r2dbc/mysql/collation/LazyInitCharCollation.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616

1717
package io.asyncer.r2dbc.mysql.collation;
1818

19+
import org.jetbrains.annotations.Nullable;
20+
1921
import java.nio.charset.Charset;
22+
import java.util.concurrent.locks.ReentrantLock;
2023

2124
/**
2225
* Character collation those NOT use cached {@link CharsetTarget} of MySQL, it will be initialized and cached
@@ -26,6 +29,9 @@
2629
*/
2730
final class LazyInitCharCollation extends AbstractCharCollation {
2831

32+
private final ReentrantLock lock = new ReentrantLock();
33+
34+
@Nullable
2935
private volatile Charset cached;
3036

3137
LazyInitCharCollation(int id, String name, CharsetTarget target) {
@@ -37,7 +43,8 @@ public Charset getCharset() {
3743
Charset cached = this.cached;
3844

3945
if (cached == null) {
40-
synchronized (this) {
46+
lock.lock();
47+
try {
4148
cached = this.cached;
4249

4350
if (cached == null) {
@@ -46,6 +53,8 @@ public Charset getCharset() {
4653
}
4754

4855
return cached;
56+
} finally {
57+
lock.unlock();
4958
}
5059
}
5160

0 commit comments

Comments
 (0)