From ad92b64ce341ea2c7366445bf9befe57c12343f7 Mon Sep 17 00:00:00 2001
From: Obai Albek <89144251+ObaiAlbek@users.noreply.github.com>
Date: Thu, 28 Aug 2025 14:06:42 +0200
Subject: [PATCH] Hand-over-Hand Locking (Java Concurrency Example)
---
.gitignore | 3 +
README.md | 15 ++
pom.xml | 62 ++++++++
src/main/java/pp/Main.java | 43 ++++++
src/main/java/pp/SimplifiedList.java | 58 ++++++++
.../java/pp/ThreadsafeSimplifiedList.java | 135 ++++++++++++++++++
6 files changed, 316 insertions(+)
create mode 100644 .gitignore
create mode 100644 README.md
create mode 100644 pom.xml
create mode 100644 src/main/java/pp/Main.java
create mode 100644 src/main/java/pp/SimplifiedList.java
create mode 100644 src/main/java/pp/ThreadsafeSimplifiedList.java
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..525681c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/target/
+/.classpath
+/.project
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6f9f415
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# Hand-over-Hand Locking (Java)
+
+## 📌 Projektbeschreibung
+Dieses Projekt implementiert eine **Thread-sichere generische Liste** in Java mithilfe von **Hand-over-Hand Locking** (auch Lock Coupling genannt).
+Die Technik wird verwendet, um **Nebenläufigkeit (Concurrency)** zu ermöglichen und gleichzeitig eine feingranulare Synchronisation zu erreichen.
+
+## ⚙️ Technologien
+- **Java 17+**
+- **Concurrency & Synchronisation (Locks, Threads)**
+- **Maven**
+
+## ▶️ Ausführen
+1. Projekt mit Maven bauen:
+ ```bash
+ mvn clean install
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..d4f8887
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,62 @@
+
+ 4.0.0
+ pp
+ pp.A4-HandOverHandLocking
+ 1.0-SNAPSHOT
+ jar
+
+
+ pp.Main
+ 10
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile exec:java
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/main/java/pp/Main.java b/src/main/java/pp/Main.java
new file mode 100644
index 0000000..b3e8df7
--- /dev/null
+++ b/src/main/java/pp/Main.java
@@ -0,0 +1,43 @@
+package pp;
+
+
+public class Main {
+ static SimplifiedList list;
+
+ static Runnable sliceSum(int start, int end, int expected) {
+ return () -> {
+ var sum = 0;
+ for (var i = start; i < end; i++) {
+ sum += list.get(i);
+ }
+ if (sum != expected) {
+ System.out.println("Fehler in "
+ + Thread.currentThread().getName() + ": " + sum);
+ }else
+ System.out.println("Kein Fehler in " + Thread.currentThread().getName() + ": " + sum);
+ };
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ list = new ThreadsafeSimplifiedList<>();
+ for (int i = 0; i < 5000; i++) {
+ list.add(i);
+ }
+ var thread0 = new Thread(sliceSum(0, 1250, 780625));
+ var thread1 = new Thread(sliceSum(1250, 2500, 2343125));
+ var thread2 = new Thread(sliceSum(2500, 3750, 3905625));
+ var thread3 = new Thread(sliceSum(3750, 5000, 5468125));
+ var start = System.currentTimeMillis();
+ thread0.start();
+ thread1.start();
+ thread2.start();
+ thread3.start();
+ thread0.join();
+ thread1.join();
+ thread2.join();
+ thread3.join();
+ System.out.printf("%s: %d ms\n", list.getClass().toString(),
+ System.currentTimeMillis() - start);
+ }
+
+}
diff --git a/src/main/java/pp/SimplifiedList.java b/src/main/java/pp/SimplifiedList.java
new file mode 100644
index 0000000..d2c7718
--- /dev/null
+++ b/src/main/java/pp/SimplifiedList.java
@@ -0,0 +1,58 @@
+package pp;
+
+public interface SimplifiedList {
+
+ /**
+ * Returns the element at the specified position in this list.
+ *
+ * @param index index of the element to return
+ * @return the element at the specified position in this list
+ * @throws Exception
+ */
+ public T get(int index);
+
+ /**
+ * Appends the specified element to the end of this list. There are no
+ * limitations on what elements may be added to this list.
+ *
+ * @param element element to be appended to this list
+ * @return true
+ * @see java.util.Collection#add(Object)
+ *
+ */
+ public boolean add(T element);
+
+ /**
+ * Replaces the element at the specified position in this list with the
+ * specified element.
+ *
+ * @param index index of the element to replace
+ * @param element element to be stored at the specified position
+ * @return the element previously at the specified position
+ * @throws Exception
+ */
+ public T set(int index, T element);
+
+ /**
+ * Returns true if this list contains no elements.
+ *
+ * @return true if this list contains no elements
+ */
+ public boolean isEmpty();
+
+ /**
+ * delayed passing through of parameter
+ *
+ * @param element element to pass through
+ * @return passed though element
+ *
+ */
+ public default T delay(T element) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ return element;
+ }
+}
diff --git a/src/main/java/pp/ThreadsafeSimplifiedList.java b/src/main/java/pp/ThreadsafeSimplifiedList.java
new file mode 100644
index 0000000..558e13a
--- /dev/null
+++ b/src/main/java/pp/ThreadsafeSimplifiedList.java
@@ -0,0 +1,135 @@
+package pp;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class ThreadsafeSimplifiedList
+ implements SimplifiedList {
+
+ private Node head;
+ private final Lock listLock = new ReentrantLock();
+
+ private class Node {
+ private U element;
+ private Node next;
+ private final Lock nodeLock;
+
+ private Node(U element, Node prev, Node next) {
+ super();
+ this.element = element;
+ this.next = next;
+ this.nodeLock = new ReentrantLock();
+ }
+ }
+
+ /**
+ * Returns the element at the specified position in this list.
+ *
+ * @param index index of the element to return
+ * @return the element at the specified position in this list
+ */
+ @Override
+ public T get(int index){
+ this.listLock.lock();
+ if (this.head == null) {
+ this.listLock.unlock();
+ throw new IndexOutOfBoundsException("The list is empty");
+ }
+
+ var ptr = this.head;
+ ptr.nodeLock.lock();
+ this.listLock.unlock();
+ for (var i = 0; i < index; i++) {
+ if (ptr.next != null) {
+ ptr.next.nodeLock.lock();
+ var savePtr = ptr;
+ ptr = ptr.next;
+ savePtr.nodeLock.unlock();
+ } else {
+ throw new IndexOutOfBoundsException(index + " out of bounds");
+ }
+ }
+
+ try {return delay(ptr.element);}
+ finally { ptr.nodeLock.unlock();}
+ }
+
+ /**
+ * Appends the specified element to the end of this list. There are no
+ * limitations on what elements may be added to this list.
+ *
+ * @param element element to be appended to this list
+ * @return true
+ * @see java.util.Collection#add(Object)
+ *
+ */
+ @Override
+ public boolean add(T element) {
+ this.listLock.lock();
+ if (this.head != null) {
+ var ptr = this.head;
+ ptr.nodeLock.lock();
+ this.listLock.unlock();
+ while (ptr.next != null) {
+ ptr.next.nodeLock.lock();
+ var savePtr = ptr;
+ ptr = ptr.next;
+ savePtr.nodeLock.unlock();
+ }
+ ptr.next = new Node<>(element, ptr, null);
+ ptr.nodeLock.unlock();
+ } else {
+ this.head = new Node<>(element, null, null);
+ this.listLock.unlock();
+ }
+ return true;
+ }
+
+ /**
+ * Replaces the element at the specified position in this list with the
+ * specified element.
+ *
+ * @param index index of the element to replace
+ * @param element element to be stored at the specified position
+ * @return the element previously at the specified position
+ */
+ @Override
+ public T set(int index, T element) {
+ this.listLock.lock();
+ if (this.head == null) {
+ this.listLock.unlock();
+ throw new IndexOutOfBoundsException("The list is empty");
+ }
+ var ptr = this.head;
+ ptr.nodeLock.lock();
+ this.listLock.unlock();
+ for (var i = 0; i < index; i++) {
+ if (ptr.next != null) {
+ ptr.next.nodeLock.lock();
+ var savePtr = ptr;
+ ptr = ptr.next;
+ savePtr.nodeLock.unlock();
+ } else
+ throw new IndexOutOfBoundsException(index + " out of bounds");
+
+ }
+ try {
+ ptr.element = element;
+ return element;
+ } finally {
+ ptr.nodeLock.unlock();
+ }
+ }
+
+ /**
+ * Returns true if this list contains no elements.
+ *
+ * @return true if this list contains no elements
+ */
+ @Override
+ public boolean isEmpty() {
+ this.listLock.lock();
+ try { return this.head == null; }
+ finally { this.listLock.unlock();}
+ }
+}