davyxu / gocoroutine

为游戏服务器设计的coroutine实现
MIT License
19 stars 7 forks source link

task 调度执行存在并发问题 #2

Open vbirds opened 2 years ago

vbirds commented 2 years ago

benchmark_test.go

package gocoroutine

import (
    //  "fmt"
    "sync"
    "testing"
)

var k int = 0
var m int = 0

func msgProc_benchmark(fc FlowControl) {

    //fmt.Println("msg 1")
    fc.Yield(dbProc_benchmark)

}

func dbProc_benchmark(fc FlowControl) {

    //fmt.Println("db 1")
    //  msgid := fc.Params().(int)
    k++
}

func recvProc_benchmark(sch *Scheduler) {

    for i := 0; i < 100000; i++ {
        sch.AddTask(msgProc_benchmark, i)
    }

}

func TestBenchmark(t *testing.T) {

    sch := NewScheduler()

    sch.Start()

    recvProc_benchmark(sch)

    sch.Exit()
    println("final k:\n", k)

}

func traditionalLogic(wg *sync.WaitGroup) {

    wg.Add(1)
    m++
    go func() {

        wg.Done()
    }()
}

// go test -bench=Benchmark -cpuprofile=cprof
func TestTraditional(t *testing.T) {

    var wg sync.WaitGroup

    for i := 0; i < 100000; i++ {

        traditionalLogic(&wg)
    }

    wg.Wait()
    println("final m:\n", m)

}

Scheduler 并不是单线程执行存在并发问题,执行结果为 99109 与 10000不符合

=== RUN   TestBenchmark
final k:
 99096
--- PASS: TestBenchmark (0.17s)
=== RUN   TestTraditional
final m:
 100000
--- PASS: TestTraditional (0.02s)
PASS
scrong1 commented 3 months ago

你都理解错了它的单线程同步的含义啊。它的意思是同一个调度中的所有任务,每个任务中fc.Yield前的代码和fc.Yield后的代码都是永远同时只有一个在执行啊,不包括fc.Yield(func)里面的func啊,那个func本来就是异步的其他地方去的啊。具体参考nodejs的async await,和lua的协程的概念啊。你在fc.Yield(func)里面的func里面计算个锤子啊