How to implement a distributed lock for coordinated access to a shared resource using sync in Golang?

In Golang, you can implement a distributed lock for coordinated access to a shared resource by using the sync package and a distributed system like Redis or etcd to manage the lock. Here's a step-by-step guide:

  1. Install the necessary dependencies:

    go get github.com/go-redis/redis/v8 // Redis client library for Golang
  2. Import the required packages:

    import ( "context" "log" "sync" "time" "github.com/go-redis/redis/v8" )
  3. Create a global Redis client:

    var redisClient *redis.Client func init() { redisClient = redis.NewClient(&redis.Options{ Addr: "localhost:6379", // Replace with your Redis server address Password: "", // If your Redis server has a password DB: 0, // Replace with the appropriate database index }) }
  4. Define a function to acquire the lock using Redis' SET command with options NX (to set the key only if it doesn't exist) and a timeout to automatically release the lock in case the lock holder crashes:

    func acquireLock(lockName string, timeout time.Duration) bool { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() success, err := redisClient.SetNX(ctx, lockName, "locked", timeout).Result() if err != nil { log.Println("Failed to acquire lock:", err) return false } return success }
  5. Define a function to release the lock by deleting the Redis key:

    func releaseLock(lockName string) { ctx := context.Background() _, err := redisClient.Del(ctx, lockName).Result() if err != nil { log.Println("Failed to release lock:", err) } }
  6. Use the lock in your code:

    func main() { lockName := "my_lock" // Acquire the lock if acquireLock(lockName, time.Second*10) { defer releaseLock(lockName) // Perform operations with the shared resource here } else { log.Println("Failed to acquire lock") } // Continue executing the rest of your code }

Make sure that your Redis server is running and accessible at the specified address.