Caching Go中的RWMutex未按预期工作
我已经使用sync.RWMutex编写了以下示例程序Caching Go中的RWMutex未按预期工作,caching,go,Caching,Go,我已经使用sync.RWMutex编写了以下示例程序 package main import ( "fmt" "sync" "time" ) // SessionData : capture session id and cc-request-number type SessionData struct { id string reqNo string } // SessionCache : cache for the SessionData
package main
import (
"fmt"
"sync"
"time"
)
// SessionData : capture session id and cc-request-number
type SessionData struct {
id string
reqNo string
}
// SessionCache : cache for the SessionData
type SessionCache struct {
sess map[SessionData]bool
sync.RWMutex
}
// InitSessionCache : Init for SessionCache
func InitSessionCache() SessionCache {
return SessionCache{sess: make(map[SessionData]bool)}
}
// Read : read value from session cache
func (s *SessionCache) Read(sd SessionData) bool {
s.RLock()
defer s.RUnlock()
_, found := s.sess[sd]
return found
}
func (s *SessionCache) Write(sd SessionData) {
s.Lock()
defer s.Unlock()
fmt.Println("Entry not found for ", sd.id, sd.reqNo, "Creating the entry now")
s.sess[sd] = true
}
func (s *SessionCache) chkDuplicate(sessionID string, Reqno string) bool {
sd := SessionData{
id: sessionID,
reqNo: Reqno,
}
found := s.Read(sd)
if !found {
s.Write(sd)
return found
}
return found
}
func main() {
mySessionData := InitSessionCache()
for i := 0; i < 10; i++ {
go mySessionData.chkDuplicate("session1", "1")
go mySessionData.chkDuplicate("session1", "1")
go mySessionData.chkDuplicate("session1", "2")
go mySessionData.chkDuplicate("session1", "2")
go mySessionData.chkDuplicate("session1", "4")
go mySessionData.chkDuplicate("session1", "2")
}
time.Sleep(300)
fmt.Println(mySessionData)
}
然而,当我在我的Windows10机器上运行相同的程序时(在VS代码上),我看到以下输出
Entry not found for session1 1 Creating the entry now
Entry not found for session1 2 Creating the entry now
Entry not found for session1 2 Creating the entry now
Entry not found for session1 2 Creating the entry now
Entry not found for session1 4 Creating the entry now
{map[{session1 1}:true {session1 2}:true {session1 4}:true] {{0 0} 0 0 0 0}}
我做错什么了吗?
为什么这在我的机器和游乐场上的行为不同?对
读取
和写入
的调用之间没有同步。您的所有goroutine都同时运行,想象一下,如果它们都运行到这一行,然后屈服于另一个goroutine:
found:=s.Read(sd)
它们都将返回false
,因为所有的goroutine都没有超过这一点。现在他们都转到下一行,并且相信found==false
,所以都执行s.Write(sd)
您需要在不解锁的情况下执行读写操作。可能是这样的:
func (s *SessionCache) TryWrite(sd SessionData) err {
s.Lock()
defer s.Unlock()
if _, found := s.sess[sd]; found {
return fmt.Errorf("Entry already exists")
}
s.sess[sd] = true
}
调用
Read
和Write
之间没有同步。您的所有goroutine都同时运行,想象一下,如果它们都运行到这一行,然后屈服于另一个goroutine:
found:=s.Read(sd)
它们都将返回false
,因为所有的goroutine都没有超过这一点。现在他们都转到下一行,并且相信found==false
,所以都执行s.Write(sd)
您需要在不解锁的情况下执行读写操作。可能是这样的:
func (s *SessionCache) TryWrite(sd SessionData) err {
s.Lock()
defer s.Unlock()
if _, found := s.sess[sd]; found {
return fmt.Errorf("Entry already exists")
}
s.sess[sd] = true
}
请参阅。不过,您的代码工作正常<代码>找到:=s.Read(sd)if!发现{s.Write(sd)——这3个操作同时运行。请参阅。但您的代码工作正常。
发现:=s.Read(sd)if!发现{s.Write(sd)
——这3个操作同时运行。