【问题标题】:How to make reading and writing to file concurent in Golang?如何在 Golang 中使读写文件并发?
【发布时间】:2015-03-04 16:25:36
【问题描述】:

我设置了一个网络服务器,并使用我自己的包来对文件进行一些写入/读取。当服务器获得一个 tcp 连接时,我启动一个不同的 goroutine 来处理每个连接的请求。在请求处理函数func中,我调用了some_package的func DoSomething()

这是 web_server.go 的代码:

 package main
 import (
    sp "./some_package"
    "log"
    "net"
    "os"
    "net/http"
   )

func main() {

  l, err := net.Listen("tcp", "0.0.0.0" + ":" + "4567")
  if err != nil {
    log.Println("Error listening:", err.Error())
    os.Exit(1)
  }
  defer l.Close()
  log.Println("Listening on 0.0.0.0:4567")  
  go func() {
    for {
        // Listen for an incoming connection.
        conn, err := l.Accept()
        if err != nil {
            log.Println("Error accepting: ", err.Error())
            os.Exit(1)
        }
        // Handle connections in a new goroutine.
        go handlerFunction(conn)
    }
  }()

  log.Printf("Setting up the Webserver...")
  err = http.ListenAndServe("0.0.0.0:"+"4568", nil)
  if err != nil {
    log.Fatal(err)
  }
}

func handlerFunction(conn net.Conn) {
  defer conn.Close()
  sp.DoSomething()
}

函数DoSomething() 读写文件。可以看到包中声明的代码:

package some_package
import (    
    "io/ioutil"
    "strconv"
    "os"
    "log"
   )
func IncrementValue(pastValue string)(newValue string){
  newValueInt, _ := strconv.Atoi(pastValue)
  return strconv.Itoa(newValueInt + 1)
}

func DoSomething() (err error){
  initialValue := "1"
  filename := "myFile.txt"
  if _, err := os.Stat(filename); err == nil {
    someText, err := ioutil.ReadFile(filename)
    if err != nil {
        log.Printf("Error reading")
        return err
    }
    newValue := IncrementValue(string(someText))

    err = ioutil.WriteFile(filename,[]byte(newValue), 0644)
    if err != nil { 
        return err
    }
  }else{
    err = ioutil.WriteFile(filename,[]byte(initialValue), 0644)
    if err != nil { 
        return err
    }
  }
  return
 }

在这种情况下,我如何使用mutex.Lockmutex.Unlock 之类的锁定机制来使对文件的读取和写入并发,因此当当前正在写入的一个例程可以阻止另一个例程读取,直到第一个写入到文件成功了吗?

我的示例是否适合在读取或写入文件时并发?

这是正确的做法吗?谢谢你

【问题讨论】:

    标签: multithreading go webserver mutex


    【解决方案1】:

    您不能同时读取和写入文件(嗯,这是可能的,但不是您描述的访问模式)。使用单个互斥锁序列化对文件的所有访问:

    var fileMutex sync.Mutex
    
    func DoSomething() {
        fileMutex.Lock()
        defer fileMutex.Unlock()
    
        //...
    }
    

    【讨论】:

    • 或者,在一个循环中使用单个 goroutine 代替互斥锁,该循环从一个通道中读取,告诉它何时修改文件,并在必要时使用一个通道来响应新值/错误。如果您知道不应该在您的程序之外修改该文件,那么您可以避免一直重新读取该文件。
    • 虽然如此,但在保护单个资源免受多次访问时,Mutex 或 RWMutex 通常仍然是最简单的选择。是的,文件处理可以改进(在这个问题的范围之外),但我通常更喜欢这 3 行代码而不是多个通道、选择和一个 goroutine。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 2016-12-10
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 2019-04-17
    • 2016-11-12
    相关资源
    最近更新 更多