ConceptioArchivearXiv CS
arXiv CSopen access

Semantic Lock: Synchronization Based on the Analysis of the Operation Conflict Graph

Unknown · 2026 · arxiv_cs
arXiv CS · Papers · License: Open Access · 2026
Open Source ↗Direct PDF ↓
clouddistributedcomputingparallelcomputing
distributed computing, parallel computing, cloud

Semantic Lock: Synchronization Based on the Analysis of the Operation Conflict Graph Denis Korotchenko a Ȉ ITMO University, Russia

Vitaly Aksenov a Ȉ ITMO University, Russia

arXiv:2606.24250v1 [cs.DC] 23 Jun 2026

Abstract This paper presents a new lock, SemanticLock, based on the conflict graph between operations. We can consider it a generalization of a read-write lock where conflicts exist between write operations and all other operations. We demonstrate the effectiveness of our lock in two applications. In the first, we design a toy data structure: an array supporting point queries and different range queries. In the second, potentially of greater interest, we augment an existing concurrent data structure, ConcurrentHashMap, with additional long-running operations.

2012 ACM Subject Classification Author: Please fill in 1 or more \ccsdesc macro Keywords and phrases concurrency, conflict graph, locks, linearizability, concurrent data structures Digital Object Identifier 10.4230/LIPIcs...

1

Introduction

When developing applications for multicore systems, it is important to use efficient concurrent data structures. These data structures encapsulate thread synchronization logic, providing a user-friendly high-level interface that ensures correctness. While commonly used implementations are highly optimized and reduce synchronization costs as much as possible, developers are often restricted by the operations they provide (e.g., just point queries). In practice, applications require custom complex operations (macrooperations) that span a large part of or even the entire data structure, such as computing an aggregate (e.g., summing all elements), performing a global transformation, or taking a consistent snapshot. The fundamental problem addressed in this paper is how to simply and effectively incorporate such complex operations into existing lock-based data structures, while providing the standard correctness guarantee — linearizability [10]. One possible direction is to decrease the execution time of a long-running operation holding the lock, which spans different techniques: reusing blocked threads to accelerate the operation holding the lock [4]; executing multiple operations in Flat Combining [8] under a single lock [1]; or applying partial persistence to speed up the execution or parallelization of specific operations [3]. Another direction, on which we focus, is to allow non-conflicting operations to run without synchronization. One of the most prominent approaches is to use transactional memory (TM) [17], including different techniques on top of it (e.g., range locks [13], range queries [16]). However, TM often incurs prohibitive metadata overhead and high abort rates, rendering it poorly suited for concurrent data structures with long-running operations. The concept of using operation semantics to manage concurrency is rooted in database compatibility matrices and semantic concurrency control [2]. In concurrent data structures, this principle forms the basis of Transactional Boosting [9], which wraps highly concurrent © Denis Korotchenko and Vitaly Aksenov; licensed under Creative Commons License CC-BY 4.0 Leibniz International Proceedings in Informatics Schloss Dagstuhl – Leibniz-Zentrum für Informatik, Dagstuhl Publishing, Germany

XX:2

Semantic Lock: Synchronization Based on the Analysis of the Operation Conflict Graph

linearizable objects inside software transactions and uses commutativity-based locks so that operations without inherent semantic conflicts can proceed concurrently. A significant problem of this approach is the need to perform inversion of operations, which can be difficult or impossible, especially for bulk operations. Additionally, it does not allow to change the internals of the data structure. The presented SemanticLock shares this use of operation-level semantic compatibility, but differs in its target and mechanism: it provides an easy-to-use locking interface that does not rely on TM, undo actions, or transaction-level versioning. Instead of turning objects into transactional objects, SemanticLock acts as an access-control layer for ordinary operations, achieving precise parallelism without additional TM costs. The first step is to replace the simple global lock with a read-write (RW) lock [5]. In this case, we need to divide operations into two sets: those that can execute concurrently (readers) and those demanding exclusive access (writers). However, in some cases, RW locks are insufficiently fine-grained due to their bipartite nature. Group Mutual Exclusion (GME) algorithms [11] offer a more flexible abstraction: operations from the same group may access the resource concurrently, while operations from different groups exclude each other. However, GME still partitions operations into mutually exclusive groups, which may be insufficient in concurrent data structures, as we show in Section 3. A later generalization, Local Group Mutual Exclusion (LGME) [14], relaxes this global conflict assumption by introducing a conflict graph between groups: processes in the same group and processes in non-conflicting groups may execute simultaneously, whereas processes from conflicting groups must exclude each other. These abstractions are close in spirit to our goal because they exploit compatibility information rather than forcing exclusive access. However, LGME is designed as a distributed mutual-exclusion problem based on group conflict relations and quorum/coterie constructions, whereas we focus on concurrent data structures. Complex data structures may expose arbitrary semantic dependencies among operation types: some operations can safely overlap with specific subsets of other operations, selfconflicts may differ from conflicts with other operations, and the desired mechanism is often a lightweight lock that can be added around existing operations. This motivates a solution that fully utilizes the conflict graph and can be simply integrated into a concurrent data structure when creating or expanding it. In this paper, we propose a design of SemanticLock, apply it to a custom data structure and extend the concurrent HashMap from the standard Java library. We evaluate our approach and show that it scales fine and works better than standard RW lock implementation.

2

Semantic Lock

Conflict Graph Model. SemanticLock is based on a concurrency control policy represented as an undirected graph G = (V, E). Each method (or set of equally conflicting methods) of the target data structure is represented by a vertex v ∈ V . An edge (u, v) ∈ E indicates a semantic conflict, meaning operations of types u and v cannot be executed concurrently. Note that u and v may be the same. In the current implementation, we require the user to provide this graph. Automatic graph generation via static analysis remains future work. Core Mechanism and Verification. SemanticLock maintains, for each vertex v ∈ V , a counter cnt[v], implemented as an AtomicInteger if (e, e) ∈ E and as a LongAdder otherwise (see Appendix A.3 for a discussion of this choice). The value of cnt[v] is the

D. Korotchenko, V. Aksenov

number of operations of type v that are running and have not yet released the lock. Upon invocation of an operation of type u, the thread repeatedly executes an optimistic acquisition phase until it acquires permission to proceed. Let N (u) = {v | (u, v) ∈ E, v ̸= u} be the set of operation types that conflict with u, excluding u itself. The acquisition phase consists of three steps: 1. Precheck. The thread reads all counters cnt[v] for v ∈ N (u). If some counter is positive, this acquisition attempt fails and the thread retries later. This step is only an optimization: it avoids modifying cnt[u] when an already visible conflict exists. 2. Reservation. The thread reserves type u. If (u, u) ∈ E, the reservation is a compareand-set on AtomicInteger cnt[u] from 0 to 1; if it fails, the acquisition attempt fails. If (u, u) ∈ / E, the thread atomically increments LongAdder cnt[u]. 3. Validation. The thread reads all counters cnt[v] for v ∈ N (u) again. If all of them are zero, the acquisition succeeds and the operation may execute. Otherwise, the thread rolls back its reservation by decrementing cnt[u] and retries the acquisition phase. After the operation completes, it releases SemanticLock by decrementing cnt[u]. Thus, an acquisition attempt may fail internally, but the data-structure operation itself is not rejected: it simply retries until it obtains permission to run. The optimistic verification protocol described above guarantees correctness, but not progress: several conflicting operations can reserve their types simultaneously and repeat the verification cycle infinitely. To avoid this, we extend SemanticLock with an extra global flag, which each thread tries to acquire (using compare-and-set(false, true)) before decrementing if the validation step fails. If the flag is acquired, the decrement is not performed and validation step is repeated until success, while other threads with conflicting operations fail at the precheck step. The correctness proof is deferred to Appendix A.1. In short, the reservation and validation steps ensure that two conflicting operation types cannot be admitted to run simultaneously. However, a continuous stream of conflicting operations may cause some pending operation to starve. SemanticLock provides an optional fairness mode based on a pendingrequest list. We explain the mechanism and prove that it provides starvation-freedom in Appendix A.2.

3

Experiments

To evaluate the practical efficiency of SemanticLock, we implemented it in Java and integrated it into two data structures: a custom concurrent array with point and range operations, and ConcurrentHashMap from the standard library extended with long-running operations. For each setting, we compare SemanticLock with two baselines: synchronization with Java’s standard ReentrantReadWriteLock (denoted by RW Lock) and non-linearizable implementation without extra synchronization used as a performance upper bound (denoted by No Lock). We report throughput under several operation distributions. We also checked the tested implementations for linearizability using the Lincheck framework [15, 12]. As expected, the No Lock baselines are not linearizable and are included only as performance upper bounds. Testing Environment. Benchmarks were conducted using a customized Synchrobench [7] framework on a machine with an Intel Xeon Gold 5128 processor (16 physical cores, 32 logical threads via hyperthreading enabled) and 64 GB of RAM.

XX:3

XX:4

Semantic Lock: Synchronization Based on the Analysis of the Operation Conflict Graph

The framework initializes a data structure and spawns T threads that repeatedly perform operations chosen according to a provided probability distribution. Each trial lasted 20 seconds: the first 10 seconds were used for warm-up, and throughput was measured during the remaining 10 seconds. We report averages over 10 independent runs after excluding outliers. In experiments, we used SemanticLock with fairness mode disabled, because Synchrobench does not model starvation scenarios. setRange

setRange

addRange

setRange

addRange

sumRange

setRange

addRange

sumRange

addRange

sumRange

point-get

sumRange

point-get

point-set

point-set

(a) conflict graph for SemanticLock

(b) SemanticLock utilization

point-get

point-set

(c) GME utilization

point-get

point-set

(d) RW lock utilization

Figure 1 Semantics of the AtomicInteger array with range queries

AtomicInteger Array with Range Queries. First, we evaluate a custom data structure: an array consisting of N = 226 AtomicInteger elements. The structure supports five operations: point-set(ind, x), point-get(ind), setRange(l, r, x) (sets all integers in a range to x), addRange(l, r, x) (adds x to all integers in a range), and sumRange(l, r) (returns the sum of integers in a range). For point operations, the index is chosen uniformly from [0, N ). For range operations, the range length |r − l| is chosen uniformly from [1, 104 ], and the start index l is chosen uniformly from [0, N − |r − l|). Our SemanticLock approach uses the conflict graph shown in Figure 1(a). Figure 1(b) shows which pairs of operations can be executed in parallel. The remaining figures highlight why a binary read-write classification (d) or even GME classification (c) can be too coarse. In the GME model, we must separate sumRange, point-get, and point-set into two groups because sumRange and point-set cannot be executed in parallel and thus cannot be in the same group. RW lock can keep only one of the compatible groups shown in figure (c). SemanticLock instead encodes exact conflict graph and allows compatible operations to proceed in parallel. Figure 2 reports six representative workloads. In the point-operation and read-only workloads, shown in Figures 2(a) and (b), SemanticLock incurs only verification and counterupdate overhead while preserving scalability and having close to No Lock throughput. For mixed workloads, the observed performance depends on the fraction of operation pairs that are compatible according to the conflict graph. In workloads dominated by concurrently admissible operations, such as point operations, range sums, and self-compatible range additions (Figures 2(d), (e) and (f)), SemanticLock maintains good scalability. In workload with a larger fraction of conflicting operations (Figure 2(c)), scalability is more limited, but SemanticLock still outperforms the RW lock baseline. Extended ConcurrentHashMap. Next, we extend Java ConcurrentHashMap with two long-running operations: keysSnapshot() (returning a snapshot of all keys) and mapValues(lambda) (applying a given function to all values). The workload consists of point reads (get), point updates (put/remove), and two new macro-operations. Arguments of point operations are chosen uniformly from [0, 220 ), and the map is initially populated by inserting each key from this range independently with probability 0.5. We compared four implementations: No Lock, RW Lock (with point read and update oper-

6 × 105

SemanticLock RW Lock No Lock

105

4 × 105

3 × 105

SemanticLock RW Lock No Lock

2 × 105

106 8

15

Threads

24

(a) 50% set, 50% get

Throughput, op / ec, log-ba ed

12 4

31

8

15

24

Threads

31

106

SemanticLock RW Lock No Lock

105

8

15

Threads

24

31

8

15

Threads

24

31

(c) 20% set, 20% get, 20% rangeSum, 20% rangeSet, 20% rangeAdd 105

SemanticLock RW Lock No Lock

105

12 4

12 4

(b) 50% get, 50% rangeSum

Throughput, ops/sec, log-based

12 4

SemanticLock RW Lock No Lock

Throughput, op / ec, log-ba ed

107

Throughput, op / ec, log-ba ed

108

XX:5

Throughput, o s/sec, log-based

Throughput, o s/sec, log-based

D. Korotchenko, V. Aksenov

SemanticLock RW Lock No Lock

104

12 4

8

15

24

Threads

12 4

31

8

15

Threads

24

31

(d) 40% get, 40% rangeSum, (e) 40% get, 10% rangeSum, (f) 5% rangeSum, 10% set, 10% rangeAdd 40% set, 10% rangeAdd 5% rangeSet, 90% rangeAdd Figure 2 Throughput of operations on AtomicInteger array under varying operation distributions read

point ops

read

update

mapValues

keysSnapshot

(a) coarse-grained conflict graph

keysSnapshot

mapValues

(b) fine-grained conflict graph

read

update

keysSnapshot

mapValues

(c) RW lock utilization

update

keysSnapshot

mapValues

(d) GME utilization

Figure 3 Semantic of the extended ConcurrentHashMap

ations denoted as readers), and two implementations with SemanticLock: SemanticLock-3 (the coarse-grained graph shown in Figure 3(a), with standard point operations grouped into a single vertex) and SemanticLock-4 (the fine-grained graph shown in Figure 3(b), with standard point operations split into get and put/remove vertices). Figure 3(c) shows a problem of RW lock: we need to choose one of the possible options: treating all point operations as readers (green) or treating get and keysSnapshot as readers (red). The GME model has the same problem: one possible option is shown in blue in Figure 3(d). SemanticLock avoids this choice: the coarse graph already separates standard operations from macro-operations, while the fine-grained graph further distinguishes point reads from point updates and admits the safe overlaps. Figure 4 reports the results for the extended ConcurrentHashMap. The trends are consistent with the array benchmark: for workloads consisting only of standard point operations or read-only operations, SemanticLock incurs additional synchronization overhead relative to the No Lock upper bound, but preserves high scalability.

Throughput, op / ec, log-ba ed

108

Throughput, op / ec, log-ba ed

Throughput, ops/sec, log-based

Semantic Lock: Synchronization Based on the Analysis of the Operation Conflict Graph

No Lock RW Lock SemanticLock-4 SemanticLock-3

102

102

12 4

8

15

Threads

24

31

12 4

102

No Lock RW Lock SemanticLock-4 SemanticLock-3

102

101 12 4

8

15

Threads

24

31

15

Threads

24

31

(b) 50% read, 50% keysSnapshot Throughput, op / ec, log-ba ed

(a) 50% read, 50% modify

8

8

102

15

Threads

24

SemanticLock-4 No Lock RW Lock SemanticLock-3

12 4

8

15

Threads

24

31

(c) 25% read, 25% modify, 25% keysS-t, 25% mapValues

No Lock RW Lock SemanticLock-4 SemanticLock-3

12 4

101

Throughput, op / ec, log-ba ed

No Lock RW Lock SemanticLock-4 SemanticLock-3

107

Throughput, op / ec, log-ba ed

XX:6

31

SemanticLock-4 No Lock RW Lock SemanticLock-3

12 4

8

15

Threads

24

31

(d) 5% read, 5% modify, (e) 10% read, 40% modify, (f) 40% read, 10% modify, 80% keysS-t, 10% mapValues 45% keysS-t, 5% mapValues 40% keysS-t, 10% mapValues Figure 4 Throughput of extended ConcurrentHashMap under varying operation distributions

For mixed workloads, both SemanticLock variants improve throughput until hyperthreading effects become visible (24 and 31 threads). The fine-grained graph used by SemanticLock-4 provides an additional, although modest, benefit when separating get from put/remove exposes extra parallelism. References 1

2

3

4

5

Vitaly Aksenov, Petr Kuznetsov, and Anatoly Shalyto. Parallel Combining: Benefits of Explicit Synchronization. In Jiannong Cao, Faith Ellen, Luis Rodrigues, and Bernardo Ferreira, editors, 22nd International Conference on Principles of Distributed Systems (OPODIS 2018), volume 125 of Leibniz International Proceedings in Informatics (LIPIcs), pages 11:1–11:16, Dagstuhl, Germany, 2019. Schloss Dagstuhl – Leibniz-Zentrum für Informatik. URL: https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs.OPODIS.2018.11, doi:10.4230/LIPIcs.OPODIS.2018.11. B. R. Badrinath and Krithi Ramamritham. Semantics-based concurrency control: Beyond commutativity. ACM Trans. Database Syst., 17(1):163–199, 1992. doi:10.1145/128765. 128771. Guy E. Blelloch and Yuanhao Wei. Verlib: Concurrent versioned pointers. In Proceedings of the 29th ACM SIGPLAN Annual Symposium on Principles and Practice of Parallel Programming, PPoPP ’24, page 200214, New York, NY, USA, 2024. Association for Computing Machinery. doi:10.1145/3627535.3638501. Trevor Brown, Aleksandar Prokopec, and Dan Alistarh. Non-blocking interpolation search trees with doubly-logarithmic running time. In Proceedings of the 25th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming, PPoPP ’20, page 276291, New York, NY, USA, 2020. Association for Computing Machinery. doi:10.1145/3332466. 3374542. P. J. Courtois, F. Heymans, and D. L. Parnas. Concurrent control with readers and writers. Commun. ACM, 14(10):667668, October 1971. doi:10.1145/362759.362813.

D. Korotchenko, V. Aksenov

6

7

8

9

10

11

12

13

14 15

16

17

Dave Dice, Yossi Lev, and Mark Moir. Scalable statistics counters. In 25th ACM Symposium on Parallelism in Algorithms and Architectures, SPAA ’13, pages 43–52. ACM, 2013. doi: 10.1145/2486159.2486182. Vincent Gramoli. More than you ever wanted to know about synchronization: synchrobench, measuring the impact of the synchronization on concurrent algorithms. In Proceedings of the 20th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming, PPoPP 2015, page 110, New York, NY, USA, 2015. Association for Computing Machinery. doi:10.1145/2688500.2688501. Danny Hendler, Itai Incze, Nir Shavit, and Moran Tzafrir. Flat combining and the synchronization-parallelism tradeoff. pages 355–364, 06 2010. doi:10.1145/1810479. 1810540. Maurice Herlihy and Eric Koskinen. Transactional boosting: a methodology for highlyconcurrent transactional objects. In Proceedings of the 13th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming, PPoPP ’08, page 207216, New York, NY, USA, 2008. Association for Computing Machinery. doi:10.1145/1345206.1345237. Maurice P. Herlihy and Jeannette M. Wing. Linearizability: a correctness condition for concurrent objects. ACM Trans. Program. Lang. Syst., 12(3):463492, July 1990. doi:10. 1145/78969.78972. Yuh-Jzer Joung. Asynchronous group mutual exclusion (extended abstract). In Proceedings of the Seventeenth Annual ACM Symposium on Principles of Distributed Computing, PODC ’98, page 5160, New York, NY, USA, 1998. Association for Computing Machinery. doi: 10.1145/277697.277706. Nikita Koval, Alexander Fedorov, Maria Sokolova, Dmitry Tsitelov, and Dan Alistarh. Lincheck: A practical framework for testing concurrent data structures on jvm. In Constantin Enea and Akash Lal, editors, Computer Aided Verification, pages 156–169, Cham, 2023. Springer Nature Switzerland. doi:10.1007/978-3-031-37706-8_8. David B. Lomet. Key range locking strategies for improved concurrency. In Proceedings of the 19th International Conference on Very Large Data Bases, VLDB ’93, page 655664, San Francisco, CA, USA, 1993. Morgan Kaufmann Publishers Inc. Aoxue Luo, Weigang Wu, Jiannong Cao, and Michel Raynal. A generalized mutual exclusion problem and its algorithm. pages 300–309, 2013. doi:10.1109/ICPP.2013.39. Aleksandr Potapov, Maksim Zuev, Evgenii Moiseenko, and Nikita Koval. Testing concurrent algorithms on jvm with lincheck and intellij idea. In Proceedings of the 33rd ACM SIGSOFT International Symposium on Software Testing and Analysis, ISSTA 2024, page 18211825, New York, NY, USA, 2024. Association for Computing Machinery. doi:10.1145/3650212. 3685301. Matthew Rodriguez, Vitaly Aksenov, and Michael Spear. Skip hash: A fast ordered map via software transactional memory. In 2025 IEEE 45th International Conference on Distributed Computing Systems (ICDCS), pages 956–966. IEEE, 2025. doi:10.1109/ICDCS63083.2025. 00097. Nir Shavit and Dan Touitou. Software transactional memory. In Proceedings of the fourteenth annual ACM symposium on Principles of distributed computing, pages 204–213, 1995.

A

SemanticLock Correctness and Fairness

A.1

Correctness Proof

We assume that the given conflict graph is sound: every pair of operation types whose overlapping executions may violate correctness is connected by an edge, and every operation type that is not safe to execute concurrently with itself has a self-loop. We first show that SemanticLock never admits two conflicting operations simultaneously. Consider two operation instances a and b of types u and v such that (u, v) ∈ E; the case

XX:7

XX:8

Semantic Lock: Synchronization Based on the Analysis of the Operation Conflict Graph

u = v corresponds to a self-loop. Suppose, for contradiction, that both instances successfully acquire SemanticLock and their protected executions overlap. Let reserve(x) denote the successful LongAdder increment or AtomicInteger compare-and-set by which operation instance x reserves its type, let validate(x) denote the validation step of x, and let release(x) denote the decrement performed when x leaves the protected region. Without loss of generality, reserve(a) precedes reserve(b) in the linearization order of atomic counter operations. Since the protected executions of a and b overlap, a does not execute release(a) before b completes its validation; otherwise, a would have already left the protected region before b entered it. Therefore, during validate(b), the counter cnt[u] is positive. Because u ∈ N (v) when u ̸= v, and because a self-loop is handled by the compare-and-set reservation when u = v, operation b cannot successfully validate while a remains reserved. It must either fail the compare-and-set in the self-loop case or observe a positive conflicting counter and roll back. This contradicts the assumption that both operations acquire successfully and overlap. So, for every edge (u, v) ∈ E, counters of adjacent conflicting types are never positive simultaneously after successful acquisition. It remains to connect this admission property to the correctness of the wrapped data structure. By the soundness assumption on the conflict graph, all pairs of operations whose overlapping executions may violate correctness are represented by edges or self-loops. SemanticLock excludes exactly such overlaps, while allowing only pairs of operations that are safe to execute concurrently according to the graph. Therefore, if each operation implementation is linearizable when executed alone or in any graph-permitted overlap, wrapping all operations with SemanticLock preserves linearizability of the resulting data structure.

A.2

Optional Fairness Guarantee

The optimistic verification protocol guarantees correctness, but not progress. In particular, an operation of type u may starve if a continuous stream of conflicting operations repeatedly acquires SemanticLock before u manages to reserve and validate its counter. We therefore provide an optional fairness mode. In fairness mode, SemanticLock maintains a concurrent list of pending requests. A request record contains the thread identifier and the requested operation type. Before starting verification, a thread appends its record to the tail of the list. The verification phase is modified as follows: during precheck, a request of type u may proceed only if two conditions hold. First, all currently executing conflicting operations are absent, as in the basic precheck. Second, there is no earlier request in the list whose type conflicts with u. If either condition fails, the thread keeps its record in the list and retries later. Once the request successfully passes the order check, it saves that fact in the record and does not check it again because no requests can appear earlier in the list. Once the request successfully passes validation and enters the protected region, it removes its record from the list; the operation itself is still protected by the counter cnt[u] until release. This rule allows non-conflicting requests to bypass one another, but it prevents a later conflicting request from overtaking an earlier one. Consider a request r of type u after it has been enqueued. Any conflicting request that is enqueued after r cannot pass precheck before r is removed from the list, because it observes r as an earlier conflicting request. Thus, only conflicting requests that were already before r in the list, together with conflicting operations already executing at the time of enqueue, can delay r. This set is finite under a finite number of threads. After those operations complete or enter and leave the protected region, no later conflicting request can bypass r, so eventually r observes both no earlier conflicting request and no executing conflicting operation, passes verification, and enters the protected region.

D. Korotchenko, V. Aksenov

Hence, the fairness mode provides starvation-freedom for conflicting operations; moreover, the number of conflicting bypasses is bounded by the number of requests already ahead of r when it is enqueued. The fairness mode is optional and can be enabled by a parameter when creating a SemanticLock instance.

A.3

Atomic Increments in Java

Initially, we started with an implementation with only AtomicIntegers. It worked in the same way as our current implementation but had very low scalability in scenarios with only point operations. The reason was the large number of conflicts during incrementAndGet of AtomicInteger and its low scalability. To make sure of it, we removed all other code from the lock method and simply incremented the counter there. The scalability continued to be very low. To mitigate the severe overhead associated with heavily contended atomic operations, modern concurrent systems frequently employ striped counters [6]. In Java, this idea is used in LongAdder. Rather than forcing concurrent threads to contend on a single memory location via single-point compare-and-set instructions, LongAdder dynamically distributes updates across an array of independent memory structures, internally referred to as cells. Under high contention, threads utilize a thread-specific hash code to route their increment operations to distinct cells, effectively transforming a global contention bottleneck into multiple parallel, uncontended updates. After changing AtomicInteger to LongAdder for non-self-conflicting operations, the performance of the point-only scenarios increased significantly. At the same time, the influence on the other scenarios was insufficient.

XX:9

Record · ID 303182 · SHA-256 2f2710ca4477a9f9
Retrieved via Conceptio — every document is proof-bundled with source, license, and retrieval metadata.