@@ -10,6 +10,14 @@ Design
10
10
- Instance confinement
11
11
- Thread/Task/Serial thread confinement
12
12
- Active object
13
+ - Code smells, identifying that a class or a subsystem could potentially be redesigned for better:
14
+ - [ Usage of ` synchronized ` with ` wait ` /` notify ` instead of concurrency utilities
15
+ ] ( #avoid-wait-notify )
16
+ - [ Nested critical sections] ( #avoid-nested-critical-sections )
17
+ - [ Extension API call within a critical section] ( #non-open-call )
18
+ - [ Large critical section] ( #minimize-critical-sections )
19
+ - [ Waiting in a loop for some result] ( #justify-busy-wait )
20
+ - [ ` ThreadLocal ` , especially when non-static] ( #threadlocal-design )
13
21
14
22
Documentation
15
23
- [ Thread safety is justified in comments?] ( #justify-document )
@@ -172,6 +180,15 @@ Time
172
180
] ( #time-going-backward )
173
181
- [ Units for a time variable are identified in the variable's name or via ` TimeUnit ` ?] ( #time-units )
174
182
- [ Negative timeouts and delays are treated as zeros?] ( #treat-negative-timeout-as-zero )
183
+
184
+ ` ThreadLocal `
185
+ - [ ` ThreadLocal ` can be ` static final ` ?] ( #tl-static-final )
186
+ - [ Can redesign a subsystem to avoid usage of ` ThreadLocal ` (esp. non-static one)?
187
+ ] ( #threadlocal-design )
188
+ - [ ` ThreadLocal ` is * not* used just to avoid moderate amount of allocation?
189
+ ] ( #threadlocal-performance )
190
+ - [ Considered replacing a non-static ` ThreadLocal ` with an instance-confined ` Map<Thread, ...> ` ?
191
+ ] ( #tl-instance-chm )
175
192
176
193
Thread safety of Cleaners and native code
177
194
- [ ` close() ` is concurrently idempotent in a class with a ` Cleaner ` or ` finalize() ` ?
@@ -216,7 +233,8 @@ https://en.wikipedia.org/wiki/Staged_event-driven_architecture).
216
233
** Instance confinement.** Objects of some root type encapsulate some complex hierarchical child
217
234
state. Root objects are solitarily responsible for the safety of accesses and modifications to the
218
235
child state from multiple threads. In other words, composed objects are synchronized rather than
219
- synchronized objects are composed. See [ JCIP 4.2, 10.1.3, 10.1.4] .
236
+ synchronized objects are composed. See [ JCIP 4.2, 10.1.3, 10.1.4] . [ TL.4] ( #tl-instance-chm ) touches
237
+ on instance confinement of thread-local state.
220
238
221
239
** Thread/Task/Serial thread confinement.** Some state is made local to a thread using top-down
222
240
pass-through parameters or ` ThreadLocal ` . See [ JCIP 3.3] . Task confinement is a variation of the
@@ -1310,6 +1328,52 @@ parameter next to a "timeout" parameter. This is the preferred option for public
1310
1328
treat negative arguments as zeros?** This is to obey the principle of least astonishment because all
1311
1329
timed blocking methods in classes from ` java.util.concurrent.* ` follow this convention.
1312
1330
1331
+ ### ` ThreadLocal `
1332
+
1333
+ <a name =" tl-static-final " ></a >
1334
+ [ #] ( #tl-static-final ) TL.1. ** Can ` ThreadLocal ` field be ` static final ` ?** There are three cases
1335
+ when a ` ThreadLocal ` cannot be static:
1336
+ - It * holds some state specific to the containing instance object* , rather than, for example,
1337
+ reusable objects to avoid allocations (which would be the same for all ` ThreadLocal ` -containing
1338
+ instances).
1339
+ - A method using a ` ThreadLocal ` may call another method (or the same method, recursively) that also
1340
+ uses this ` ThreadLocal ` , but on a different containing object.
1341
+ - There is a class (or ` enum ` ) modelling a specific type of ` ThreadLocal ` usage, and there are only
1342
+ limited number of instances of this class in the JVM: i. e. all are constants stored in
1343
+ ` static final ` fields, or ` enum ` constants.
1344
+
1345
+ If a usage of ` ThreadLocal ` doesn't fall into either of these categories, it can be ` static final ` .
1346
+
1347
+ There is an inspection "ThreadLocal field not declared static final" in IntelliJ IDEA which
1348
+ corresponds to this item.
1349
+
1350
+ <a name =" threadlocal-design " ></a >
1351
+ [ #] ( #threadlocal-design ) TL.2. Doesn't a ** ` ThreadLocal ` mask issues with the code, such as poor
1352
+ control flow or data flow design?** Is it possible to redesign the system without using
1353
+ ` ThreadLocal ` , would that be simpler? This is especially true for instance-level (non-static)
1354
+ ` ThreadLocal ` fields; see also [ TL.1] ( #tl-static-final ) and [ TL.4] ( #tl-instance-chm ) about them.
1355
+
1356
+ See [ Dc.2] ( #threading-flow-model ) about the importance of articulating the control flow and the data
1357
+ flow of a subsystem which may help to uncover other issues with the design.
1358
+
1359
+ <a name =" threadlocal-performance " ></a >
1360
+ [ #] ( #threadlocal-performance ) TL.3. Isn't a ** ` ThreadLocal ` used only to reuse some small heap
1361
+ objects, cheap to allocate and initialize, that would otherwise need to be allocated relatively
1362
+ infrequently?** In this case, the cost of accessing a ` ThreadLocal ` would likely outweigh the
1363
+ benefit from reducing allocations. The evidence should be supplied that introducing a ` ThreadLocal `
1364
+ shortens the GC pauses and/or increases the overall throughput of the system.
1365
+
1366
+ <a name =" tl-instance-chm " ></a >
1367
+ [ #] ( #tl-instance-chm ) TL.4. If the threads which execute code with usage of a non-static
1368
+ ` ThreadLocal ` are long-living and there is a fixed number of them (e. g. workers of a fixed-sized
1369
+ ` ThreadPoolExecutor ` ) and there is a greater number of shorter-living ` ThreadLocal ` -containing
1370
+ objects, was it considered to ** replace the instance-level ` ThreadLocal<Val> ` with a
1371
+ ` ConcurrentHashMap<Thread, Val> threadLocalValues ` confined to the objects** , accessed via like
1372
+ ` threadLocalValues.get(Thread.currentThread()) ` ? This approach requires some confidence and
1373
+ knowledge about the threading model of the subsystem (see [ Dc.2] ( threading-flow-model ) ), though it
1374
+ may also be trivial if Active Object pattern is used (see [ Dn.2] ( #use-patterns ) ), but is much
1375
+ friendlier to GC because no short-living weak references are produced.
1376
+
1313
1377
### Thread safety of Cleaners and native code
1314
1378
1315
1379
<a name =" thread-safe-close-with-cleaner " ></a >
0 commit comments