← Back to Go Course | Chapter 11: Concurrency | Lesson 7 of 8

Race Conditions क्या हैं

एक race condition तब होती है जब दो goroutines एक ही समय में data के एक जैसे टुकड़े को छूने के लिए दौड़ते हैं, और जो भी 'जीते' वह result को अप्रत्याशित रूप से बदल देता है।
Syntax
go
var mu sync.Mutex
var shared int

mu.Lock()
shared++          // access shared data only while locked
mu.Unlock()

// detect races: go run -race main.go

What a Race Condition Looks Like

जब दो या ज़्यादा goroutines बिना किसी coordination के एक ही variable को पढ़ते और लिखते हैं, final result अप्रत्याशित timing पर निर्भर करता है -- वही program अलग-अलग runs में अलग, कभी-कभी गलत, results produce कर सकता है।

उदाहरण: What a Race Condition Looks Like

markup
package main

import (
	"fmt"
	"sync"
)

func main() {
	total := 0
	var wg sync.WaitGroup
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			total++ // unsynchronized: a real race in production code
		}()
	}
	wg.Wait()
	fmt.Println("total (may vary if truly racy):", total)
}

Detecting Races with -race

Go एक race detector के साथ आता है, 'go run -race' या 'go test -race' से enabled, जो memory accesses को instrument करता है और genuine race देखने पर involved goroutines और lines report करता है, भले ही output उस run में सही दिखा हो।

Note: जब code में data share करने वाले goroutines शामिल हों हमेशा CI में -race के साथ tests चलाएं।

उदाहरण: Detecting Races with -race

bash
go run -race main.go

⚠️ Run this in your own terminal or Node.js environment.

Fixing a Race with a Mutex

shared data पर race का standard fix इसके हर access को एक mutex से सुरक्षित करना है, यह सुनिश्चित करते हुए कि किसी भी instant पर सिर्फ एक goroutine variable पढ़ या लिख सके।

उदाहरण: Fixing a Race with a Mutex

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the packages this program uses
import (
	"fmt"
	"sync"
)

// main is where the program starts running
func main() {
	// Declare mu with the zero value of its type
	var mu sync.Mutex
	// Short declaration: create total and infer the type
	total := 0
	// Declare wg with the zero value of its type
	var wg sync.WaitGroup
	// Loop: repeat while the condition holds
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		// Start this call in a new goroutine (runs concurrently)
		go func() {
			defer wg.Done()
			mu.Lock()
			total++
			mu.Unlock()
		}()
	}
	wg.Wait()
	fmt.Println("total:", total)
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. यह मान लेना कि testing के दौरान 'आमतौर पर काम करने वाले' program में कोई race condition नहीं -- races timing-dependent होती हैं और production load द्वारा उजागर होने तक छुप सकती हैं।
  2. एक goroutine से shared variable पढ़ना जबकि दूसरा इसे लिखता है, बिना mutex या channel के, यह मानते हुए कि साधारण reads हमेशा सुरक्षित हैं।
  3. कभी 'go test -race' या 'go run -race' न चलाना, उन races को miss करते हुए जिन्हें सिर्फ race detector reliably उजागर करता है।
चैप्टर सारांश
  • एक race condition तब होती है जब कई goroutines बिना synchronization के concurrently shared data access करते हैं और कम से कम एक इसे लिखता है।
  • Races अप्रत्याशित results produce करती हैं जो runs के बीच बदल सकते हैं, सिर्फ inspection से debug करना मुश्किल बनाते हुए।
  • Go का built-in race detector (-race flag) runtime पर races पकड़ने के लिए किसी program को instrument करता है।
  • एक race ठीक करने का मतलब है access को एक mutex, channel से synchronize करना, या shared mutable state को पूरी तरह टालना।
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.