mirror of
https://github.com/tmrts/go-patterns.git
synced 2024-11-22 04:56:09 +03:00
synchronization/mutex: implement synchronization mutex/lock pattern
This commit is contained in:
parent
f978e42036
commit
4fa57a0eb9
@ -52,7 +52,7 @@ A curated collection of idiomatic design & application patterns for Go language.
|
||||
| Pattern | Description | Status |
|
||||
|:-------:|:----------- |:------:|
|
||||
| [Condition Variable](/synchronization/condition_variable.md) | Provides a mechanism for threads to temporarily give up access in order to wait for some condition | ✘ |
|
||||
| [Lock/Mutex](/synchronization/mutex.md) | Enforces mutual exclusion limit on a resource to gain exclusive access | ✘ |
|
||||
| [Lock/Mutex](/synchronization/mutex.md) | Enforces mutual exclusion limit on a resource to gain exclusive access | ✔ |
|
||||
| [Monitor](/synchronization/monitor.md) | Combination of mutex and condition variable patterns | ✘ |
|
||||
| [Read-Write Lock](/synchronization/read_write_lock.md) | Allows parallel read access, but only exclusive access on write operations to a resource | ✘ |
|
||||
| [Semaphore](/synchronization/semaphore.md) | Allows controlling access to a common resource | ✔ |
|
||||
|
53
synchronization/mutex.go
Normal file
53
synchronization/mutex.go
Normal file
@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
//dictionary inherits the mutex lock
|
||||
type dictionary struct {
|
||||
sync.Mutex
|
||||
rel map[string]string
|
||||
}
|
||||
|
||||
//add a new key value pare if the given key is not present in the map
|
||||
//returns an error if the given key is already present
|
||||
func (d *dictionary) putIfAbsent(key string, value string) error {
|
||||
//Locks the object, add the key-value pare to the map, and then unlock the object
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
if _, isPresent := d.rel[key]; isPresent {
|
||||
return fmt.Errorf("key [%s] is already present in the dictionary", key)
|
||||
}
|
||||
d.rel[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func newDictionary() dictionary {
|
||||
return dictionary{
|
||||
rel: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
d := newDictionary()
|
||||
keys := []string{"foo", "bar", "baz", "bar"}
|
||||
values := []string{"value1", "value2", "value3", "value4"}
|
||||
for i := 0; i < len(keys); i++ {
|
||||
// Starts a new goroutine
|
||||
// that that add to the dictionary as a key string representation of i % 7
|
||||
// and string representation of i as a value
|
||||
go func(index int) {
|
||||
err := d.putIfAbsent(keys[index], values[index])
|
||||
if err != nil {
|
||||
//print the error
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
time.Sleep(time.Second * 2)
|
||||
//print the result
|
||||
fmt.Println(d.rel)
|
||||
}
|
64
synchronization/mutex.md
Normal file
64
synchronization/mutex.md
Normal file
@ -0,0 +1,64 @@
|
||||
# Mutex/Lock pattern
|
||||
A mutex is a synchronization pattern that allows exclusive access to shared data by locking and unlocking.
|
||||
|
||||
## Implementation
|
||||
|
||||
```go
|
||||
package mutex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//dictionary inherits the mutex lock
|
||||
type Dictionary struct {
|
||||
sync.Mutex
|
||||
rel map[string]string
|
||||
}
|
||||
|
||||
func New() Dictionary {
|
||||
return Dictionary{
|
||||
rel: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
//add a new key value pare if the given key is not present in the map
|
||||
//returns an error if the given key is already present
|
||||
func (d *Dictionary) PutIfAbsent(key string, value string) error {
|
||||
d.Lock() //lock the object
|
||||
defer d.Unlock() //unlock the object when the work is done
|
||||
//return the error if key is already present in the map
|
||||
if _, isPresent := d.rel[key]; isPresent {
|
||||
return fmt.Errorf("key [%s] is already present in the dictionary", key)
|
||||
}
|
||||
d.rel[key] = value
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
func main() {
|
||||
d := mutext.New()
|
||||
keys := []string{"foo", "bar", "baz", "bar"}
|
||||
values := []string{"value1", "value2", "value3", "value4"}
|
||||
for i := 0; i < len(keys); i++ {
|
||||
// Starts a new goroutine
|
||||
// that that add to the dictionary as a key string representation of i % 7
|
||||
// and string representation of i as a value
|
||||
go func(index int) {
|
||||
err := d.putIfAbsent(keys[index], values[index])
|
||||
if err != nil {
|
||||
//print the error
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
time.Sleep(time.Second * 2)
|
||||
//print the result
|
||||
fmt.Println(d.rel)
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue
Block a user