我试图在golang中从地图实现读/写的锁定版本,但它并没有返回所需的结果。
package main
import (
"sync"
"fmt"
)
var m = map[int]string{}
var lock = sync.RWMutex{}
func StoreUrl(id int, url string) {
for {
lock.Lock()
defer lock.Unlock()
m[id] = url
}
}
func LoadUrl(id int, ch chan string) {
for {
lock.RLock()
defer lock.RUnlock()
r := m[id]
ch <- r
}
}
func main() {
go StoreUrl(125, "www.google.com")
chb := make(chan string)
go LoadUrl(125, chb);
C := <-chb
fmt.Println("Result:", C)
}
输出结果为:
Result:
意味着价值不是通过渠道返回的,我没有得到。没有锁定/ goroutines它似乎工作正常。我做错了什么?
代码也可以在这里找到:
答案 0 :(得分:1)
没有睡眠或某种IO的无限循环总是坏主意。
在您的代码中,如果您在StoreUrl
的开头放置一个print语句,您会发现它永远不会被打印,即go例程从未启动过,go调用是设置有关这个新的信息go调度程序的某些运行队列中的例程,但调度程序尚未运行以安排该任务。你如何运行调度程序?睡眠/ IO /频道读/写。
另一个问题是你的无限循环正在锁定并试图再次锁定,这将导致它死锁。延迟仅在函数退出后运行,并且由于无限循环,该函数将永远不会退出。
下面是修改后的代码,它使用sleep来确保每个执行线程都有时间完成它的工作。
package main
import (
"sync"
"fmt"
"time"
)
var m = map[int]string{}
var lock = sync.RWMutex{}
func StoreUrl(id int, url string) {
for {
lock.Lock()
m[id] = url
lock.Unlock()
time.Sleep(1)
}
}
func LoadUrl(id int, ch chan string) {
for {
lock.RLock()
r := m[id]
lock.RUnlock()
ch <- r
}
}
func main() {
go StoreUrl(125, "www.google.com")
time.Sleep(1)
chb := make(chan string)
go LoadUrl(125, chb);
C := <-chb
fmt.Println("Result:", C)
}
修改:@Jaun在评论中提到,您也可以使用runtime.Gosched()
代替睡眠。
答案 1 :(得分:1)
延迟不正确的使用,在函数结束时延迟执行,而不是语句。
development:
encoding: unicode
username: postgres
password: postgres
pool: 20
timeout: 5000
wait_timeout: 10
min_messages: warning
adapter: postgresql
host: localhost
database: auction_dev
port: 5432
或
func StoreUrl(id int, url string) {
for {
func() {
lock.Lock()
defer lock.Unlock()
m[id] = url
}()
}
}
我们无法控制go例程的顺序,所以添加time.Sleep()来控制命令。
代码在这里: