Golang的sync.RWLock似乎会导致死锁?

huangapple go评论77阅读模式
英文:

golang sync.RWLock appears to create deadlock?

问题

我一直在使用一个RWLock来进行mysql数据库的读取,但是似乎偶尔会出现以下代码锁定程序的情况,因为它在等待解锁:

// 从指定的表中的键中返回字符串值,如果第三个参数不区分大小写,则应将其设置为false。
func (self *DBStore) GetString(table string, key string, vargs...interface{}) (output string) {
    
    defer func() { fmt.Println("GETSTRING Freeing Mutex!") }()
    self.mutex.RLock()
    fmt.Println("GETSTRING Got Mutex!")
    defer self.mutex.RUnlock()

    self.Get(table, key, &output, vargs...)
    return

}

// 在指定的表中的键上检索值。
func (self *DBStore) Get(table string, key string, output interface{}, vargs...interface{}) (found bool) {
    
    defer func() { fmt.Println("GET Freeing Mutex!") }()
    fmt.Println("Requesting Mutex")
    self.mutex.RLock()
    fmt.Println("GET Got Mutex!")
    defer self.mutex.RUnlock()

现在通过上面的代码,我可以看到我实际上不需要在这里执行RLock,我可以简单地将其删除,但是我认为读锁不应该干扰另一个读锁。而且它似乎是间歇性的,通常我需要运行几次相同的操作才会再次发生。

程序的输出是:

Requesting Mutex
GET Got Mutex!
GET Freeing Mutex!
GETSTRING Got Mutex!
Requesting Mutex

然后它就永远停在那里,被锁定。我在这里漏掉了什么?

任何信息都将不胜感激!

go版本go1.4 darwin/amd64

英文:

I've been using an RWLock for reads on a mysql database, but it appears that intermittently the following code locks the programs as it waits for a unlock?

// Returns string value from key in table specified, third parameter should be set to false if it shouldn't be case senstive.
func (self *DBStore) GetString(table string, key string, vargs...interface{}) (output string) {
	
	defer func() { fmt.Println("GETSTRING Freeing Mutex!") }()
	self.mutex.RLock()
	fmt.Println("GETSTRING Got Mutex!")
	defer self.mutex.RUnlock()

	self.Get(table, key, &output, vargs...)
	return

}

// Retreive a value at key in table specified.
func (self *DBStore) Get(table string, key string, output interface{}, vargs...interface{}) (found bool) {
	
	defer func() { fmt.Println("GET Freeing Mutex!") }()
	fmt.Println("Requesting Mutex")
	self.mutex.RLock()
	fmt.Println("GET Got Mutex!")
	defer self.mutex.RUnlock()

Now with the above, I can see that I really don't need to perform the RLock here and I can simply enough just remove it, but I was under the impression read locks shouldn't interfere with another read lock. Also it seems to be intermittent, and it usually takes me a few times of running the same thing before it reoccurs.

Output of program is:

Requesting Mutex
GET Got Mutex!
GET Freeing Mutex!
GETSTRING Got Mutex!
Requesting Mutex

and then it just sits forever, locked. What am I missing here?

Any info would be appreciated!

go version go1.4 darwin/amd64

答案1

得分: 2

在思考了关于连续使用 RLock 时的问题之后,现在有了一些明确的想法。

我没有在这里记录锁的情况,现在清楚的是,发生了一种情况,即一个锁插入了两个连续的 RLock 之间。

基本上,锁被排队了。

(线程1)GetString -> 请求读锁
(线程1)GetString -> 获得读锁
(线程2)Set -> 请求写锁(被阻塞,排队)
(线程1)Get -> 请求读锁(被阻塞,排队)

来自 http://golang.org/src/sync/rwmutex.go?s=862:888#L19

34 如果 atomic.AddInt32(&rw.readerCount, 1) < 0 {
35 // 有一个写入者正在等待,等待它。
36 runtime_Semacquire(&rw.readerSem)
37 }

英文:

After thinking about the problem with the back to back RLock, it makes sense.

What I'm not logging here is the Locks, and what is clear now is a condition is occurring where a Lock is getting in between the back to back RLocks.

Basically the lock is queued.

(Thread 1) GetString -&gt; Request Read Lock
(Thread 1) GetString -&gt; Got Read Lock
(Thread 2) Set -&gt; Request Write Lock (Blocked, queued.)
(Thread 1) Get -&gt; Request Read Lock (Blocked, queued.)

From http://golang.org/src/sync/rwmutex.go?s=862:888#L19

> 34 if atomic.AddInt32(&rw.readerCount, 1) < 0 {
> 35 // A writer is pending, wait for it.
> 36 runtime_Semacquire(&rw.readerSem)
> 37 }

huangapple
  • 本文由 发表于 2015年1月22日 13:20:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/28081740.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定