The sync module provides synchronization primitives for concurrent programming, including mutexes and read-write mutexes. These primitives help protect shared data structures from race conditions when using Harneet's do/await concurrency model.
Overview
The sync module offers two main types of synchronization primitives:
Mutex: Provides mutual exclusion for protecting shared resources
RWMutex: Optimized for scenarios with frequent reads and infrequent writes
package main
import sync, fmt
var sharedCounter = 0
var counterMutex, _ = sync.NewMutex()
function incrementCounter(name string, times int) string {
for var i = 0; i < times; i = i + 1 {
var _, err = counterMutex.Lock()
if err != None {
return "lock error: " + err.Error()
}
sharedCounter = sharedCounter + 1
fmt.Printf("%s: counter = %d\n", name, sharedCounter)
var _, unlockErr = counterMutex.Unlock()
if unlockErr != None {
return "unlock error: " + unlockErr.Error()
}
}
return name + " completed"
}
function main() {
// Use with existing concurrency
var task1 = do incrementCounter("Task1", 5)
var task2 = do incrementCounter("Task2", 5)
var result1 = await(task1)
var result2 = await(task2)
fmt.Println("Results:", result1, result2)
fmt.Println("Final counter:", sharedCounter)
}
Best Practices
Avoiding Deadlocks
Consistent Lock Ordering: Always acquire multiple locks in the same order
Timeout Patterns: Use TryLock operations with retry logic
Minimal Critical Sections: Keep locked sections as short as possible
Performance Considerations
Use RWMutex for Read-Heavy Workloads: When reads significantly outnumber writes
Avoid Lock Contention: Design data structures to minimize shared state
Consider Lock-Free Alternatives: For simple operations like counters
var success, err = mutex.Lock()
if err != None {
// Handle error appropriately
fmt.Println("Lock failed:", err)
return
}
// Use blank identifier only when errors can be safely ignored
var _, _ = mutex.Unlock()
import sync
var counter = 0
var counterMutex, _ = sync.NewMutex()
function safeIncrement() int {
var _, _ = counterMutex.Lock()
counter = counter + 1
var result = counter
var _, _ = counterMutex.Unlock()
return result
}
function safeGet() int {
var _, _ = counterMutex.Lock()
var result = counter
var _, _ = counterMutex.Unlock()
return result
}