package main import ( "fmt" "sync" "time" ) var counter int var mutex = &sync.RWMutex{} // Creating a RWMutex func main() { for i := 0; i < 5; i++ { go reader(i + 1) } for i := 0; i < 3; i++ { go writer(i + 1) } time.Sleep(10 * time.Second) } func reader(id int) { for { mutex.RLock() // Acquires a read lock fmt.Printf("Reader %d: Counter value: %d\n", id, counter) time.Sleep(1 * time.Second) mutex.RUnlock() // Releases the read lock } } func writer(id int) { for { mutex.Lock() // Acquires a write lock counter++ fmt.Printf("Writer %d: Counter value: %d\n", id, counter) time.Sleep(1 * time.Second) mutex.Unlock() // Releases the write lock } }
package main import ( "fmt" "sync" ) type Person struct { age int mu sync.RWMutex } func (p *Person) getAge() int { p.mu.RLock() // Acquires a read lock defer p.mu.RUnlock() // Defer release of read lock return p.age } func (p *Person) setAge(age int) { p.mu.Lock() // Acquires a write lock defer p.mu.Unlock() // Defer release of write lock p.age = age } func main() { p := &Person{} p.setAge(25) fmt.Println(p.getAge()) // Output: 25 }In this example, we have defined a struct named Person, which has an age field and a RWMutex named mu. We have defined two methods named getAge() and setAge() that get and set the age field of the Person struct, respectively. The getAge() method acquires a read lock on the RWMutex using RLock() to read the age field, whereas the setAge() method acquires a write lock on the RWMutex using Lock() to set the age field. The defer statement is used to ensure that the lock is released after the function returns, even if an error occurs. We are using RWMutex to provide a way for multiple goroutines to read the age field of the Person struct safely, while only one goroutine can write to it at a time.