Sobes.tech
Middle+

Quelles sont les opérations atomiques, quels sont leurs types, et quand et comment est-il préférable de les utiliser?

sobes.tech IA

Réponse de l'IA

Les opérations atomiques sont des opérations sur la mémoire dont l'exécution garantit qu'elles se terminent complètement ou ne commencent pas du tout, et elles ne peuvent pas être interrompues par d'autres opérations concurrentes. Elles sont indivisibles et sûres pour les threads au niveau matériel.

Dans Go, le paquet sync/atomic fournit un ensemble de fonctions pour effectuer des opérations atomiques :

Fonction Description
AddInt32 Ajoute de manière atomique une valeur à int32.
AddInt64 Ajoute de manière atomique une valeur à int64.
AddUint32 Ajoute de manière atomique une valeur à uint32.
AddUint64 Ajoute de manière atomique une valeur à uint64.
AddUintptr Ajoute de manière atomique une valeur à uintptr.
CompareAndSwapInt32 Compare et échange (CAS) int32 de manière atomique.
CompareAndSwapInt64 Compare et échange (CAS) int64 de manière atomique.
CompareAndSwapUint32 Compare et échange (CAS) uint32.
CompareAndSwapUint64 Compare et échange (CAS) uint64.
CompareAndSwapUintptr Compare et échange (CAS) uintptr.
CompareAndSwapPointer Compare et échange (CAS) unsafe.Pointer.
LoadInt32 Charge de manière atomique la valeur de int32.
LoadInt64 Charge de manière atomique la valeur de int64.
LoadUint32 Charge de manière atomique la valeur de uint32.
LoadUint64 Charge de manière atomique la valeur de uint64.
LoadUintptr Charge de manière atomique la valeur de uintptr.
LoadPointer Charge de manière atomique la valeur de unsafe.Pointer.
StoreInt32 Stocke de manière atomique la valeur de int32.
StoreInt64 Stocke de manière atomique la valeur de int64.
StoreUint32 Stocke de manière atomique la valeur de uint32.
StoreUint64 Stocke de manière atomique la valeur de uint64.
StoreUintptr Stocke de manière atomique la valeur de uintptr.
StorePointer Stocke de manière atomique la valeur de unsafe.Pointer.
SwapInt32 Échange de manière atomique les valeurs de int32.
SwapInt64 Échange de manière atomique les valeurs de int64.
SwapUint32 Échange de manière atomique les valeurs de uint32.
SwapUint64 Échange de manière atomique les valeurs de uint64.
SwapUintptr Échange de manière atomique les valeurs de uintptr.
SwapPointer Échange de manière atomique les valeurs de unsafe.Pointer.

Il est préférable d'utiliser des opérations atomiques dans les cas où une synchronisation simple et de bas niveau est requise pour l'accès à des variables communes, comme des compteurs ou des drapeaux, sans utiliser de mutex. Elles offrent des coûts minimaux et de meilleures performances dans de tels scénarios.

Exemple d'utilisation d'un compteur atomique :

package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

func main() {
	var counter int64
	var wg sync.WaitGroup

	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			// Incrémentation atomique du compteur
			atomic.AddInt64(&counter, 1)
			wg.Done()
		}()
	}

	wg.Wait()
	// Chargement atomique de la valeur du compteur
	fmt.Println("Compteur final :", atomic.LoadInt64(&counter))
}

Exemple d'utilisation de CompareAndSwap :

package main

import (
	"fmt"
	"sync/atomic"
)

func main() {
	var value int32 = 10

	// Tentative d'échange de la valeur si elle est actuellement 10, en 20
	swapped := atomic.CompareAndSwapInt32(&value, 10, 20)
	fmt.Println("Échange effectué :", swapped) // true
	fmt.Println("Valeur :", value)   // 20

	// Tentative d'échange de la valeur si elle est actuellement 10, en 30
	swapped = atomic.CompareAndSwapInt32(&value, 10, 30)
	fmt.Println("Échange effectué :", swapped) // false
	fmt.Println("Valeur :", value)   // 20
}

Il est important de se rappeler que les opérations atomiques fonctionnent avec des types primitifs (entiers, pointeurs). Pour la synchronisation d'accès à des structures de données plus complexes ou l'exécution d'opérations bloquantes, des mutex ou d'autres mécanismes de synchronisation sont toujours nécessaires. Une utilisation excessive ou incorrecte des opérations atomiques peut entraîner des erreurs difficiles à détecter ou une baisse des performances.