账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    在递归中,当线程数不定时如何等所有线程都结束才返回
    36
    0

    代码功能

    扫描一个文件,如果文件中有-f flist1.f, 那么新打开一个goroutine对flist1.f进行扫描, 如果是top.v, 那么直接保存到一个列表里。

    代码

    package main
    
    import (
        "bufio"
        "errors"
        "fmt"
        "io"
        "log"
        "os"
        "regexp"
        "strings"
    )
    
    type intlist []int
    
    var dlog *log.Logger
    
    type slist struct {
        fn    []string
        count int
    }
    
    func main() {
        logFile, err := os.Create("harriszh.log")
        c := make(chan int)
        defer logFile.Close()
        if err != nil {
            log.Fatalln("open file error!")
        }
        dlog = log.New(logFile, "[Debug]", log.Llongfile)
        var s slist
        path := os.Args[1]
        s.getList(path, c)
        i := 0
        for i < s.count {
            <-c
            i++
        }
        s.showdec()
    }
    
    func (s *slist) showdec() {
        dlog.Printf("########### BEGIN #################\n")
        for _, k := range s.fn {
            dlog.Printf("%s\n", k)
        }
        dlog.Printf("############# END ###############\n")
    }
    
    func (s *slist) getList(path string, c chan int) error {
        scommentRe := regexp.MustCompile(`^\s*(.*?)\s*//.*`)
        //the space is removed by TrimSpace
        flistRe := regexp.MustCompile(`^-f\s+(.*)`)
        fin, err := os.Open(path)
        defer fin.Close()
        if err != nil {
            return errors.New("NOEXIST")
        }
        bufi := bufio.NewReader(fin)
        for {
            lineStat, err := bufi.ReadString('\n')
            if err == io.EOF {
                c <- 1
                break
            }
            if err != nil {
                fmt.Fprintf(os.Stderr, "can't read : %v\n", err)
                os.Exit(1)
            }
            newline := strings.Replace(lineStat, "\n", "", -1)
            linewc := scommentRe.ReplaceAllString(newline, "$1")
            linewc = strings.TrimSpace(linewc)
            if linewc != "" {
                if flistRe.MatchString(linewc) {
                    newpath := flistRe.FindStringSubmatch(linewc)[1]
                    s.count++
                    go s.getList(newpath, c)
                } else {
                    s.fn = append(s.fn, linewc)
                }
            }
        }
        return nil
    }

    测试文件

    makefile

    TARGET=getlist
    SRC = getlist.go
    
    default: build
    
    help:
        @echo "available commands:"
        @echo "    make build"
        @echo "    make run00"
        @echo "    make debug"
        @echo "    make clean"
    
    build:
        go build -gcflags "-N -l" -o ${TARGET} ${SRC}
    
    release:
        go build -ldflags "-s" -o ${TARGET} ${SRC}
    
    #   source /opt/go/src/runtime/runtime-gdb.py
    #   set args -input top.v -output out.v
    #   b main.main
    
    run run00: 
        ./${TARGET} flist.f
    
    
    debug: 
        delve ./${TARGET}
    
    clean:
        rm -rf ${TARGET}
    
    
    .PHONY: clean 

    flist.f

    test00.v
    -f f1.f
    //comment0
    test01.v
    -f f2.f
    //no f3.f
    -f f3.f

    f1.f

    test10.v
    //comment
    test11.v

    f2.f

    test20.v
    test21.v
    //comment
    
    
    ## 问题
    用了进程计数器,不过问题是还没等所有进程都完,main里面的for i < s.count就开始运行了
    比较复杂的方案是把所有读取的行都通过chan返回,直到没有内容了
    不知道有没有简单的方案
    
    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 最爱で毛毛熊 普通会员 1楼

      在递归中,当线程数不定时,我们通常需要使用一些同步机制来确保所有线程都结束。这通常可以通过使用互斥锁(mutex)或信号量(semaphore)来实现。

      互斥锁是一种线程同步机制,它允许多个线程在同一时刻访问共享资源,但不允许多个线程同时访问。当所有线程都结束时,互斥锁会自动释放,从而确保所有线程都结束。

      信号量是一种线程同步机制,它允许多个线程在同一时刻访问共享资源,但只有一个线程可以修改共享资源的状态。当所有线程都结束时,信号量会自动释放,从而确保所有线程都结束。

      除此之外,我们还可以使用条件变量(condition variable)来实现线程同步。条件变量是一种可以改变线程状态的同步机制,它允许一个线程在另一个线程结束之前或之后改变自己的状态。当所有线程都结束时,条件变量会自动释放,从而确保所有线程都结束。

      在Python中,我们可以使用threading.Condition类来实现条件变量。以下是一个简单的示例:

      ```python import threading

      创建一个条件变量

      condition = threading.Condition()

      def worker(): while True: # 获取条件变量的状态 state = condition.wait()

          # 如果状态改变,则退出循环
          if state != threading.Condition().wait():
              break
      
          # 执行任务
          print('Worker:', state)
      

      创建一个线程并启动它

      thread = threading.Thread(target=worker) thread.start()

      等待所有线程结束

      condition.join() ```

      在这个示例中,我们首先创建了一个条件变量。然后,我们创建了一个线程,并启动它。在每次线程执行完毕后,我们调用condition.wait()来获取线程的状态,并检查状态是否改变。如果状态改变,则退出循环。否则,线程会继续执行任务。当所有线程都结束时,我们调用condition.join()来等待所有线程结束。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部