Mastering tldb Distributed Locks in Go and Java: A Practical Guide

This article explains how tldb implements distributed locks, details the lock, tryLock, and unlock APIs, and provides step‑by‑step Go and Java code examples—including blocking, non‑blocking, and spin‑lock patterns—plus test results to illustrate correct usage.

Programmer DD
Programmer DD
Programmer DD
Mastering tldb Distributed Locks in Go and Java: A Practical Guide

Distributed locks are essential in distributed systems, and tldb offers a simple, reliable lock mechanism that mimics object‑level locking.

tldb Distributed Lock API

lock(string, int) : blocks until the lock is acquired; the first argument is the lock name, the second is the maximum hold time in seconds.

tryLock(string, int) : attempts to acquire the lock and returns immediately; if successful, it returns a key, otherwise an empty result.

unlock(string) : releases the lock using the key returned by lock/tryLock.

The lock functions are implemented in the MQ module, and client libraries exist for Java, Go, Python, and JavaScript. The lock is server‑controlled, making it language‑agnostic.

Lock (string, int) Usage

The first parameter specifies the lock object (e.g., "abc"), and the second parameter defines the lock’s maximum lease time in seconds. If the lease expires without an explicit unlock, the server forcibly releases the lock.

Unlock(string) Usage

After completing business logic, the client must call unlock(key) to release the lock; otherwise, the server will release it after the timeout.

TryLock (string, int) Usage

Unlike lock, tryLock is non‑blocking; it returns immediately with a key if the lock is obtained, or an empty result if the lock is already held.

Go Example

import "github.com/donnie4w/tlmq-go/cli"

// Blocking lock
sc := cli.NewMqClient("ws://127.0.0.1:5001", "mymq=123")
sc.Connect()
key, err := sc.Lock("testlock", 3)
if err != nil {
    // handle error
} else {
    defer sc.UnLock(key)
    // business logic
}

// Non‑blocking tryLock
if key, ok := sc.TryLock("testlock2", 3); ok {
    defer sc.UnLock(key)
    // business logic
}

// Spin‑lock using tryLock
var key string
for {
    if v, ok := sc.TryLock("testlock", 3); ok {
        key = v
        break
    } else {
        <-time.After(100 * time.Millisecond)
    }
}
defer sc.UnLock(key)
// business logic

Java Example

Maven dependency:

<dependency>
    <groupId>io.github.donnie4w</groupId>
    <artifactId>tlmq-j</artifactId>
    <version>0.0.2</version>
</dependency>

Blocking lock:

MqClient mc = new SimpleClient("ws://127.0.0.1:5001", "mymq=123");
mc.connect();
String key = null;
try {
    key = mc.lock("testlock", 3);
    // business logic
} finally {
    if (key != null) {
        mc.unLock(key);
    }
}

Non‑blocking tryLock:

MqClient mc = new SimpleClient("ws://127.0.0.1:5001", "mymq=123");
mc.connect();
String key = null;
try {
    key = mc.tryLock("testlock", 3);
    // business logic
} finally {
    if (key != null) {
        mc.unLock(key);
    }
}

Functional Test Results

Concurrent threads acquiring the same lock using lock and tryLock produce the following outcomes:

Spinning with tryLock to emulate blocking behavior yields:

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backendtldb
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.