# Concurrent Sorted Linked List Performance Analysis
## Introduction
This repository documents the implementation and performance testing of a concurrent, sorted linked list in Java, addressing **Question 2, Part 1** of the assignment *Multiple Threads and Performance Improvement*.
We try to implement a concurrent sorted linked list in different manners to get thread-safe and suitable performance on this data structure.
## Content
The core objective was to compare the thread safety and efficiency of three different concurrency control mechanisms: `synchronized`, `ReentrantLock`, and the specialized `ReentrantReadWriteLock`.
### A. List Structure (`SortList.java`, `Entry.java`)
\ No newline at end of file
-**Sorted Invariant**: The list is maintained in ascending order. The `add` method is designed to be the sorting mechanism, always finding the correct insertion point.
-**Sentinel Nodes**: The list uses `Integer.MIN_VALUE` and `Integer.MAX_VALUE` as sentinels to simplify boundary checks in all methods.
-**Correctness Checks**: The `SortList` abstract class includes:
-`checkSorted()`: Verifies that the list structure is intact and in ascending order after concurrent modifications.
-**Thread-Safe Counters**: `length`, `containSuccess`, `removeFailure`, etc., are protected by the same lock as the list structure to ensure accurate, atomic reporting.
| `SyncList.java` | Intrinsic Lock | Uses the `synchronized` keyword, locking the entire list object (`this`) for every method call. | Forces all operations (reads and writes) to be serial, leading to low read performance. |
| `LockList.java` | Exclusive Lock | Uses a `java.util.concurrent.locks.ReentrantLock`. Provides slightly better control than `synchronized` but still forces all operations to be exclusive. | Performance is similar to `SyncList` because parallelism is blocked for reads. |
| `RWLockList.java` | Read/Write Lock (Optimized) | Uses a `ReentrantReadWriteLock` to distinguish between reads and writes. | **High Performance**: Allows multiple threads to read (`contain`) concurrently (`readLock`), while still forcing writes (`add`/`remove`) to be exclusive (`writeLock`). |
---
## 🧪 II. Benchmark Results
The benchmark was executed across three cases varying the number of threads and the total sequence length to observe performance under low, medium, and high contention.
### Performance Summary (Execution Time in milliseconds)
| Case | Threads | Total Length | Operation | Synchronization (ms) | RWLock (ms) | Lock (ms) | Speedup Factor (RWLock vs. Sync) |
> Results for Case 2 and 3 exhibit the same patterns with proportionate increases in time.
---
## 💡 III. Interpretation and Conclusion
### 1. The Power of Parallel Reads (CONTAIN Phase)
- The primary finding is the overwhelming performance lead of the `RWLockList` in the `CONTAIN` operation.
- The **6.9× speedup** in Case 2 shows the efficiency of the shared read lock. Since 8 threads could read the list simultaneously, the total execution time was reduced to nearly the time of a single read operation.
- The `synchronized` and `ReentrantLock` implementations were forced to process read requests one-by-one, leading to unacceptable serialization delays.
### 2. Efficiency in Contention (REMOVE Phase)
- The `RWLockList` completed the `REMOVE` operation in Case 1 **2.1 times faster** than `SyncList`, even though writing must be serialized (exclusive).
- This suggests that the underlying implementation of the `ReentrantReadWriteLock`'s write queue is more efficient at managing high-contention requests than the general-purpose `synchronized` keyword, allowing threads waiting for the lock to acquire it and release it faster.
### 3. Validation of Thread Safety
-**Data Integrity**: The final list lengths (e.g., 13,862) and operation counts are identical across all three implementations for every test case. This is the ultimate proof that no race conditions occurred, and all locking mechanisms successfully protected the list structure.
-**Correctness Check**: The consistent result *“The List is sorted”* after thousands of concurrent add and remove operations confirms that the core list invariant was maintained throughout the concurrent test.
---
### ✅ Conclusion
> For data structures that are read more frequently than they are written, the **Read/Write Lock (`RWLockList`)** is the mandatory choice for achieving high throughput and maximum parallelism without sacrificing thread safety.