php小編草莓將為您介紹如何解決共享資源的訪問沖突問題。在多線程或多進(jìn)程編程中,當(dāng)多個(gè)線程或進(jìn)程同時(shí)訪問共享資源時(shí),可能會(huì)導(dǎo)致數(shù)據(jù)不一致或錯(cuò)誤的結(jié)果。為了解決這個(gè)問題,可以使用互斥鎖、信號量、條件變量等同步機(jī)制來保證資源的互斥訪問。通過合理使用這些同步機(jī)制,我們可以有效地解決共享資源的訪問沖突問題,保證程序的正確性和穩(wěn)定性。
問題內(nèi)容
有一個(gè)測試服務(wù)有 2 個(gè)請求。這些請求使用 actualorders
變量形式的共享資源。假設(shè)正在運(yùn)行數(shù)百個(gè)并行查詢,則 actualorders 變量中可能會(huì)發(fā)生數(shù)據(jù)沖突。特別是當(dāng)我循環(huán)遍歷數(shù)組時(shí)。為了防止這種情況,使用 mutex
是否足夠,就像我在下面的示例中所做的那樣?
ma??in.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) } }
登錄后復(fù)制
解決方法
像您一樣使用互斥鎖可以防止數(shù)據(jù)爭用。不過,您的實(shí)施還可以改進(jìn)。
您可以使用 rwmutex
,對 getorders
函數(shù)使用讀鎖,對 createorder
函數(shù)使用鎖。這將允許在寫入時(shí)對 actualorders
變量進(jìn)行獨(dú)占訪問,但允許共享讀取:
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() }
登錄后復(fù)制