In this article, we will explore the CompareAndSwapPointer() Function in sync/atomic package in Go in details, along with examples.
Introduction:
The Go programming language, often referred to as Golang, provides robust concurrency support through goroutines and channels. However, there are situations where low-level atomic operations are required to optimize concurrent code. The sync/atomic package in Go offers a set of functions for atomic memory access, which helps in achieving this optimization. One such function is CompareAndSwapPointer. This article will provide a detailed explanation of the CompareAndSwapPointer function, its use cases, and a practical example.
What is CompareAndSwapPointer Function ?
The CompareAndSwapPointer function is part of the sync/atomic package in Go. It performs an atomic compare-and-swap operation on a pointer value. The function prototype is as follows:
Syntax:
func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
- addr: A pointer to the memory address storing the pointer value that needs to be compared and potentially swapped.
- old: The pointer value that is expected to be stored at the memory address.
- new: The pointer value that will replace the old value if the comparison is successful.
- Return value: swapped – A boolean value that indicates whether the swap was successful (true) or not (false).
The CompareAndSwapPointer function performs an atomic operation, ensuring that the comparison and swap occur without being interrupted by other goroutines. This is essential when working with shared memory in concurrent code.
Example
Let’s consider a simple example to demonstrate the use of the CompareAndSwapPointer function. Suppose we have a shared data structure that multiple goroutines access and modify concurrently.
package main
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
)
type Data struct {
value int
}
func main() {
var dataPtr unsafe.Pointer
var wg sync.WaitGroup
data := &Data{value: 10}
dataPtr = unsafe.Pointer(data)
wg.Add(2)
go func() {
defer wg.Done()
newData := &Data{value: 20}
swapped := atomic.CompareAndSwapPointer(&dataPtr, unsafe.Pointer(data), unsafe.Pointer(newData))
fmt.Println("Goroutine 1 - Swapped:", swapped)
}()
go func() {
defer wg.Done()
newData := &Data{value: 30}
swapped := atomic.CompareAndSwapPointer(&dataPtr, unsafe.Pointer(data), unsafe.Pointer(newData))
fmt.Println("Goroutine 2 - Swapped:", swapped)
}()
wg.Wait()
finalData := (*Data)(dataPtr)
fmt.Println("Final value:", finalData.value)
}
In this example, we have a Data struct with an integer value. We use unsafe.Pointer to store the address of the data and perform an atomic compare-and-swap operation using CompareAndSwapPointer. We have two goroutines trying to update the value concurrently. Only one of them will succeed in updating the value, ensuring that the data’s integrity is preserved.
Conclusion
The CompareAndSwapPointer function in Go’s sync/atomic package provides a low-level atomic operation to ensure safe access and modification of shared memory in concurrent code. It is essential to use atomic operations when working with shared memory in concurrent programming to avoid data races and ensure data consistency. This article has provided a detailed explanation of the CompareAndSwapPointer function and demonstrated its usage through an example.
To check more Go related articles. Pls click given below link:
https://techieindoor.com/category/leetcode/
https://pkg.go.dev/net/[email protected]