在go函数中golang太多打开的文件,goroutine

时间:2016-08-08 08:52:28

标签: go goroutine

package main

import (
    "os"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(1024 * 1024)
    for i := 0; i < (1024 * 1024); i++ {
        go func(index int) {
            if f, e := os.Open(i); e == nil {
                //blah blah
                f.Close()
            }
        }(i)
    }
    wg.Done()
}

如果运行该程序会出现以下错误。 “打开太多打开的文件” 请告诉我们如何消除错误。

1 个答案:

答案 0 :(得分:5)

您的系统资源不足,因为您使用了太多的文件描述符而没有释放足够的文件描述符。您需要限制程序中的并发性。

为此,您可以使用缓冲通道作为计数信号量。

sem := make(chan struct{}, 12) // 12 is the maximum number of 
                                // concurrent processes that may run at any time

现在您可以将方法修改为:

func main() {
    var wg sync.WaitGroup
    wg.Add(1024 * 1024)

    for i := 0; i < (1024 * 1024); i++ {
        go func(index int) {

            // if there are already 12 goroutines running, below send will block
            // and a new file wont be open
            sem <- struct{}{}

            // once this goroutine finishes, empty the buffer by one
            // so the next process may start (another goroutine blocked on
            // above send will now be able to execute the statement and continue)
            defer func() { <-sem }()

            // wg.Done must be deferred after a read from sem so that
            // it executes before the above read
            defer wg.Done()

            if f, e := os.Open(strconv.Itoa(index)); e != nil {
                // handle file open failure
                return
            }
            defer f.Close()
            // handle open file
        }(i)
    }

    wg.Wait()
    close(sem)
}

您对wg.Done的使用也不正确。阅读它here

(请注意,此代码旨在提供有关此类问题的基本概念。您还可以参考此问题以获取一个有效的示例:Go worker pool with repetitive queue structure