php editor Strawberry will introduce you how to solve the access conflict problem of shared resources. In multi-threaded or multi-process programming, when multiple threads or processes access shared resources at the same time, data inconsistency or erroneous results may result. In order to solve this problem, synchronization mechanisms such as mutex locks, semaphores, and condition variables can be used to ensure mutually exclusive access to resources. By rationally using these synchronization mechanisms, we can effectively solve the problem of access conflicts of shared resources and ensure the correctness and stability of the program.
There is a test service with 2 requests. These requests use shared resources in the form of actualorders
variables. Assuming hundreds of parallel queries are running, data conflicts may occur in the actualorders variable. Especially when I'm looping through the array. To prevent this, would it be enough to use mutex
, like I do in the example below?
main.go:
package main import ( "encoding/json" "errors" "fmt" "net/http" "os" "time" ) type Order struct { Room string `json:"room"` UserEmail string `json:"email"` From time.Time `json:"from"` To time.Time `json:"to"` } var ActualOrders = []Order{} var mutex sync.Mutex func getOrders(responseWriter http.ResponseWriter, request *http.Request) { userEmail := request.URL.Query().Get("email") results := []Order{} mutex.Lock() for _, item := range ActualOrders { if item.UserEmail == userEmail { results = append(results, item) } } mutex.Unlock() bytes, err := json.Marshal(results) if err != nil { http.Error(responseWriter, err.Error(), http.StatusInternalServerError) return } responseWriter.Header().Set("Content-type", "application/json") responseWriter.WriteHeader(http.StatusOK) responseWriter.Write(bytes) } func createOrder(responseWriter http.ResponseWriter, request *http.Request) { var newOrder Order requestBody := request.Body defer request.Body.Close() err := json.NewDecoder(requestBody).Decode(&newOrder) if err != nil { http.Error(responseWriter, err.Error(), http.StatusBadRequest) return } mutex.Lock() for _, order := range ActualOrders { if !(newOrder.To.Before(order.From) || newOrder.From.After(order.To)) { http.Error(responseWriter, http.StatusText(http.StatusConflict), http.StatusConflict) return } } ActualOrders = append(ActualOrders, newOrder) mutex.Unlock() responseWriter.WriteHeader(http.StatusCreated) } func main() { mux := http.NewServeMux() mux.HandleFunc("/orders", getOrders) mux.HandleFunc("/order", createOrder) err := http.ListenAndServe(":8080", mux) if errors.Is(err, http.ErrServerClosed) { fmt.Printf("server closed\n") } else if err != nil { fmt.Printf("error starting server: %s\n", err) os.Exit(1) } }
Using a mutex like you did can prevent data races. However, your implementation can be improved.
You can use rwmutex
to use read locks on the getorders
function and locks on the createorder
function. This will allow exclusive access to the actualorders
variable when writing, but allow shared reading:
var mutex sync.RWMutex func getOrders(responseWriter http.ResponseWriter, request *http.Request) { ... mutex.RLock() ... mutex.RUnlock() } func createOrder(responseWriter http.ResponseWriter, request *http.Request) { ... mutex.Lock() for _, order := range ActualOrders { ... } ActualOrders = append(ActualOrders, newOrder) mutex.Unlock() }
The above is the detailed content of How to resolve access conflicts on shared resources?. For more information, please follow other related articles on the PHP Chinese website!