duanjiao5261
2012-09-04 14:37
浏览 156
已采纳

使用golang的goroutine时如何实现计数器?

I'm trying to make a queue struct that have push and pop functions.

I need to use 10 threads push and another 10 threads pop data, just like i did in the code below.

Questions : 1. I need to print out how much i have pushed/popped, but i don't know how to do that. 2. Is there anyway to speed up my code ? the code is too slow for me.

package main

import (
    "runtime"
    "time"
)

const (
    DATA_SIZE_PER_THREAD = 10000000
)

type Queue struct {
    records string
}


func (self Queue) push(record chan interface{}) {
    // need push counter
    record <- time.Now()
}

func (self Queue) pop(record chan interface{}) {
    // need pop counter
    <- record
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    //record chan
    record := make(chan interface{},1000000)
    //finish flag chan
    finish := make(chan bool)
    queue := new(Queue)
    for i:=0; i<10; i++ {
        go func() {
            for j:=0; j<DATA_SIZE_PER_THREAD; j++ {
                queue.push(record)
            }
            finish<-true
        }()
    }
    for i:=0; i<10; i++ {
        go func() {
            for j:=0; j<DATA_SIZE_PER_THREAD; j++ {
                queue.pop(record)
            }
            finish<-true
        }()
    }
    for i:=0; i<20; i++ {
        <-finish
    }
}
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • drasv0904 2012-09-04 15:37
    已采纳

    There are a few things you should fix.

    • The methods on the Queue type should have pointer receivers. Otherwise, every method call will create a copy of the current queue type and any changes to queue fields will not persist beyond the method call itself.

    • Waiting for all routines to finish, can be done using a sync.WaitGroup. This is specifically what it was designed for.

    • Maintaining a thread-safe push/pop counter inside the queue type can be done by using the sync/atomic package.

    As far as speed goes, from your example, I am not quite sure what you are trying to achieve. Any optimizations might come up if you elaborate on that a little.

    Here is an example I modified from your code:

    package main
    
    import (
        "log"
        "runtime"
        "sync"
        "sync/atomic"
        "time"
    )
    
    const SizePerThread = 10000000
    
    type Queue struct {
        records string
        count   int64
    }
    
    func (q *Queue) push(record chan interface{}) {
        record <- time.Now()
    
        newcount := atomic.AddInt64(&q.count, 1)
        log.Printf("Push: %d", newcount)
    }
    
    func (q *Queue) pop(record chan interface{}) {
        <-record
    
        newcount := atomic.AddInt64(&q.count, -1)
        log.Printf("Pop: %d", newcount)
    }
    
    func main() {
        var wg sync.WaitGroup
    
        runtime.GOMAXPROCS(runtime.NumCPU())
    
        record := make(chan interface{}, 1000000)
        queue := new(Queue)
    
        // We are launching 20 goroutines.
        // Let the waitgroup know it should wait for as many
        // of them to finish.
        wg.Add(20)
    
        for i := 0; i < 10; i++ {
            go func() {
                defer wg.Done()
    
                for j := 0; j < SizePerThread; j++ {
                    queue.push(record)
                }
            }()
    
            go func() {
                defer wg.Done()
    
                for j := 0; j < SizePerThread; j++ {
                    queue.pop(record)
                }
            }()
        }
    
        // Wait for all goroutines to finish.
        wg.Wait()
    }
    
    打赏 评论
  • dongyi2159 2012-09-09 20:18

    Answer to question 1: As jimt suggested, sync/atomic has functions for atomically updating a counter, which may be useful to you.

    Answer to question 2: Reduce the value of DATA_SIZE_PER_THREAD, or better yet, use the program

    package main
    func main() {}
    

    which produces the same output as your program in a more efficent way.

    Seriously though, I understand you have written a small program to explore some concepts. Your program contains a number of issues however. This is not the time to worry about speed, it is the time to learn some fundamental concepts.

    打赏 评论

相关推荐 更多相似问题