Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Caching Go中的RWMutex未按预期工作_Caching_Go - Fatal编程技术网

Caching Go中的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

我已经使用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
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个操作同时运行。