goroutine或多线程在golang中无法工作。

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

goroutine or multithreading is not working in golang

问题

我正在尝试在Go语言中实现多线程。我能够实现goroutine,但它的工作结果与预期不符。以下是我准备的示例程序:

func test(s string, fo *os.File) {
    var s1 [105]int
    count := 0
    for x := 1000; x < 1101; x++ {
        s1[count] = x
        count++
    }

    for i := range s1 {
        runtime.Gosched()
        sd := s + strconv.Itoa(i)
        var fileMutex sync.Mutex
        fileMutex.Lock()
        fmt.Fprintf(fo, sd)
        defer fileMutex.Unlock()
    }
}

func main() {
    fo, err := os.Create("D:/Output.txt")
    if err != nil {
        panic(err)
    }
    for i := 0; i < 4; i++ {
        go test("bye", fo)
    }
}

输出结果为:good0bye0bye0bye0bye0good1bye1bye1bye1bye1good2bye2bye2bye2bye2...等等。

上述程序将创建一个文件,并在文件中写入"Hello"和"bye"。

我的问题是,我想创建5个线程,并希望使用不同的线程处理不同的值。如果你看上面的示例,它会打印4次"bye"。

我希望的输出结果是使用5个线程,如下所示:

good0bye0good1bye1good2bye2...等等。

你有什么办法可以实现这个要求吗?

英文:

I was trying to implement multithreading in golang. I am able to implement go routines but it is not working as expected. below is the sample program which i have prepared,

func test(s string, fo *os.File) {
	var s1 [105]int
	count :=0
	for x :=1000; x&lt;1101;x++ {
	s1[count] = x;
		count++
	}

	//fmt.Println(s1[0])
	for i := range s1 {
		runtime.Gosched() 
		sd := s + strconv.Itoa(i)
		var fileMutex sync.Mutex
		fileMutex.Lock()
		fmt.Fprintf(fo,sd)
		defer fileMutex.Unlock()
	}
}

func main() {
	fo,err :=os.Create(&quot;D:/Output.txt&quot;)
	if err != nil {
		panic(err)
	}
	for i := 0; i &lt; 4; i++ {
		go test(&quot;bye&quot;,fo) 

	}

	

}

OUTPUT - good0bye0bye0bye0bye0good1bye1bye1bye1bye1good2bye2bye2bye2bye2.... etc.
the above program will create a file and write "Hello" and "bye" in the file.

My problem is i am trying to create 5 thread and wanted to process different values values with different thread. if you will see the above example it is printing "bye" 4 times.

i wanted output like below using 5 thread,

good0bye0good1bye1good2bye2....etc....

any idea how can i achieve this?

答案1

得分: 3

首先,你需要在主函数中阻塞,直到所有其他goroutine返回。你程序中的互斥锁没有阻塞任何东西,而且由于它们在每次循环中重新初始化,它们甚至不会在自己的goroutine中阻塞。如果你不是从函数中返回,就不能延迟解锁,你需要在每次循环迭代中显式解锁。你没有使用数组中的任何值(尽管你应该使用切片),所以我们可以完全删除它。在一个行为良好的程序中,你也不需要runtime.GoSched,它在这里没有任何作用。

一个等效的可以完整运行的程序如下:

var wg sync.WaitGroup

var fileMutex sync.Mutex

func test(s string, fo *os.File) {
    defer wg.Done()
    for i := 0; i < 105; i++ {
        fileMutex.Lock()
        fmt.Fprintf(fo, "%s%d", s, i)
        fileMutex.Unlock()
    }
}

func main() {
    fo, err := os.Create("D:/output.txt")
    if err != nil {
        log.Fatal(err)
    }
    for i := 0; i < 4; i++ {
        wg.Add(1)
        go test("bye", fo)

    }
    wg.Wait()
}

最后,没有理由尝试从多个goroutine向单个文件写入连续的值,这样做效率更低。如果你希望整个文件中的值有序,你仍然需要使用单个goroutine。

英文:

First, you need to block in your main function until all other goroutines return. The mutexes in your program aren't blocking anything, and since they're re-initialized in each loop, they don't even block within their own goroutine. You can't defer an unlock if you're not returning from the function, you need to explicitly unlock in each iteration of the loop. You aren't using any of the values in your array (though you should use a slice instead), so we can drop that entirely. You also don't need runtime.GoSched in a well-behaved program, and it does nothing here.

An equivalent program that will run to completion would look like:

var wg sync.WaitGroup

var fileMutex sync.Mutex

func test(s string, fo *os.File) {
	defer wg.Done()
	for i := 0; i &lt; 105; i++ {
		fileMutex.Lock()
		fmt.Fprintf(fo, &quot;%s%d&quot;, s, i)
		fileMutex.Unlock()
	}
}

func main() {
	fo, err := os.Create(&quot;D:/output.txt&quot;)
	if err != nil {
		log.Fatal(err)
	}
	for i := 0; i &lt; 4; i++ {
		wg.Add(1)
		go test(&quot;bye&quot;, fo)

	}
	wg.Wait()
}

Finally though, there's no reason to try and write serial values to a single file from multiple goroutines, and it's less efficient to do so. If you want the values ordered over the entire file, you will need to use a single goroutine anyway.

huangapple
  • 本文由 发表于 2016年9月10日 02:28:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/39417713.html
匿名

发表评论

匿名网友

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

确定