我们最近一直在讨论操作系统类中的线程,我想到了一个问题.
由于Go,(和Java)使用用户空间线程而不是内核线程,这是否意味着您无法有效利用多个内核,因为操作系统只为进程分配CPU时间而不是线程本身?
Go地图类型线程是否安全?我有一个程序,有许多goroutines读取和写入地图类型.如果我需要实施保护机制,那么最好的方法是什么?
通道将通信 - 值的交换 - 与同步相结合 - 保证两个计算(goroutine)处于已知状态.
如何使用Google Go中的频道执行互斥锁功能?
package main
import "sync"
var global int = 0
var m sync.Mutex
func thread1(){
m.Lock()
global = 1
m.Unlock()
}
func thread2(){
m.Lock()
global = 2
m.Unlock()
}
func main(){
go thread1()
go thread2()
}
Run Code Online (Sandbox Code Playgroud) 在他对这个问题的回答中: Golang for Windows的不稳定行为? user @distributed建议锁定/同步对并发goroutines上的共享变量的访问.
我怎样才能做到这一点?
更多关于这个问题:
我得到views了同时在几个goroutine 上运行的代码(带有闭包的返回函数):
func makeHomeHandler() func(c *http.Conn, r *http.Request) {
views := 1
return func(c *http.Conn, r *http.Request) {
fmt.Fprintf(c, "Counting %s, %d so far.", r.URL.Path[1:], views)
views++
}
}
Run Code Online (Sandbox Code Playgroud)
看起来IO函数占用了它的时间,因此我得到了这种输出:
Counting monkeys, 5 so far.
Counting monkeys, 5 so far.
Counting monkeys, 5 so far.
Counting monkeys, 8 so far.
Counting monkeys, 8 so far.
Counting monkeys, 8 so far.
Counting monkeys, 11 so far.
Run Code Online (Sandbox Code Playgroud)
它增加很好,但是当它被打印时,我可以看到操作打印+递增根本不是原子的.
如果我将其更改为:
func makeHomeHandler() func(c …Run Code Online (Sandbox Code Playgroud) 我使用Go和Gin来设置我的网站,并想知道数据库访问时间.我使用goroutine所以如果不使用类似线程的东西,我必须改变几乎每个函数来做它.Go有很好的方法吗?
这是一个简单的Go http(tcp)连接测试脚本
func main() {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
}))
defer ts.Close()
var wg sync.WaitGroup
for i := 0; i < 2000; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
resp, err := http.Get(ts.URL)
if err != nil {
panic(err)
}
greeting, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
panic(err)
}
fmt.Printf("%s", i, greeting)
}(i)
}
wg.Wait()
}
Run Code Online (Sandbox Code Playgroud)
如果我在Ubuntu中运行它,我得到:
panic: Get http://127.0.0.1:33202: dial tcp 127.0.0.1:33202: too many open files
其他帖子说要确保Close …
就我而言,我有成千上万的goroutines同时工作work().我也有一个sync()goroutine.当sync启动时,我需要任何其他的goroutine同步作业完成后暂停了一段时间.这是我的代码:
var channels []chan int
var channels_mutex sync.Mutex
func work() {
channel := make(chan int, 1)
channels_mutex.Lock()
channels = append(channels, channel)
channels_mutex.Unlock()
for {
for {
sync_stat := <- channel // blocked here
if sync_stat == 0 { // if sync complete
break
}
}
// Do some jobs
if (some condition) {
return
}
}
}
func sync() {
channels_mutex.Lock()
// do some sync
for int i := 0; i != len(channels); i++ …Run Code Online (Sandbox Code Playgroud) 我是Go语言的新手,所以如果我的问题非常基本,请原谅.我写了一个非常简单的代码:
func main(){
var count int // Default 0
cptr := &count
go incr(cptr)
time.Sleep(100)
fmt.Println(*cptr)
}
// Increments the value of count through pointer var
func incr(cptr *int) {
for i := 0; i < 1000; i++ {
go func() {
fmt.Println(*cptr)
*cptr = *cptr + 1
}()
}
}
Run Code Online (Sandbox Code Playgroud)
count的值应该增加一个循环运行的次数.考虑案例:
循环运行100次 - >计数值为100(循环运行100次时这是正确的).
循环运行> 510次 - >计数值为508或510.即使它是100000也会发生.
我在8核处理器机器上运行它.
我写了以下程序:
package main
import (
"fmt"
)
func processevents(list chan func()) {
for {
//a := <-list
//a()
}
}
func test() {
fmt.Println("Ho!")
}
func main() {
eventlist := make(chan func(), 100)
go processevents(eventlist)
for {
eventlist <- test
fmt.Println("Hey!")
}
}
Run Code Online (Sandbox Code Playgroud)
由于频道事件列表是一个缓冲频道,我想我应该得到输出"嘿!"的100倍,但它只显示一次.我的错误在哪里?
Go为什么要写封闭频道?
虽然可以使用这个value, ok := <-channel成语从频道中读取,因此可以测试ok结果是否可以打开一个封闭的频道:
// reading from closed channel
package main
import "fmt"
func main() {
ch := make(chan int, 1)
ch <- 2
close(ch)
read(ch)
read(ch)
read(ch)
}
func read(ch <-chan int) {
i,ok := <- ch
if !ok {
fmt.Printf("channel is closed\n")
return
}
fmt.Printf("read %d from channel\n", i)
}
Run Code Online (Sandbox Code Playgroud)
输出:
read 2 from channel
channel is closed
channel is closed
Run Code Online (Sandbox Code Playgroud)
在Playground上运行"从封闭频道阅读"
写入可能关闭的频道更复杂,因为如果您只是在频道关闭时尝试写,Go会感到恐慌:
//writing to closed channel
package main
import (
"fmt"
) …Run Code Online (Sandbox Code Playgroud)