Member-only story

Some Coding Challenges: Implementing a Lock.

applied.math.coding
2 min readMar 27, 2024

--

The challenge is to implement a lock in Java by only using synchronized, wait, notify as constructs.

The lock shall work as follows:

var lock = new Lock();

private void doSomething(){
lock.lock();
// no other thread shall be able to go here in the meantime
lock.unlock();
}

A solution written in Java:

class Lock {
boolean isLocked = false;

public synchronized void lock() {
while (isLocked) {
try {
wait();
} catch (InterruptedException e) {
// neglect
}
}
isLocked = true;
}

public synchronized void unlock() {
isLocked = false;
notify();
}
}

You can use this like so:

var task = new Runnable() {
Lock countLock = new Lock();
int count = 0;

@Override
public void run() {
while (true) {
countLock.lock();
if (count < 1000) {
count += 1;
System.out.println(Thread.currentThread().getName() + " :" + count);
} else {
countLock.unlock();
break;
}
countLock.unlock();
}
System.out.println("finished " + Thread.currentThread().getName());
}
};

(new Thread(task)).start();
(new Thread(task)).start();

Note, this lock is not a so called Reentrant Lock. For instance doing this

lock.lock();
lock.lock();
lock.unlock();
lock.unlock();

would not work. The thread could not pass the second lock because the isLocked remains true.

The next challenge is to alter the above code to make it an Reentrant Lock.

class Lock {
boolean isLocked = false;
int lockerCounter = 0;
Thread owner;

public synchronized void lock() {
while (Thread.currentThread() != owner && isLocked) {
try {
wait();
} catch (InterruptedException e) {
// neglect
}
}
lockerCounter += 1;
isLocked = true;
owner = Thread.currentThread();
}

public synchronized void unlock() {
lockerCounter -= 1;
if (lockerCounter == 0) {
isLocked = false;
owner = null;
notify();
}
}
}

The simple idea is to check additionally if the thread that wants to acquire the lock is the one that currently holds it. Also, we need to keep track of how often the lock has been acquired before unlocking it.

For instance

lock();
lock();

unlock(); // here we don't want to release the lock
unlock();

Thank you for reading!

--

--

applied.math.coding
applied.math.coding

Written by applied.math.coding

I am a Software Developer - Java, Rust, SQL, TypeScript - with strong interest doing research in pure and applied Mathematics.

No responses yet