Skip to content

Latest commit

 

History

History
148 lines (80 loc) · 9.02 KB

chanbarrier_test.go.md

File metadata and controls

148 lines (80 loc) · 9.02 KB

File: chanbarrier_test.go

chanbarrier_test.go 文件的作用是测试 Go 语言中的通道屏障。通道屏障是一种同步原语,用于在不同的 goroutine 之间同步时序。在 Go 1.12 中,通过对一组通道进行 close 操作来实现通道屏障。在 Go 1.13 及之后的版本中,通过新增 sync/barrier 包来实现通道屏障。

该测试文件主要包含了对 sync/barrier 包的测试。测试场景包括多个 goroutine 通过通道屏障同步执行,并检查执行的正确性和效率。具体的测试包括了:

  1. 测试使用 sync/barrier 包实现的通道屏障在多个 goroutine 同步执行时的正确性和效率。
  2. 测试当有一个 goroutine 提前退出时,通道屏障是否仍然能够正常工作。
  3. 测试通道屏障在使用 close 操作实现时的正确性和效率。
  4. 测试当使用 close 操作实现时,有一个 goroutine 提前退出时,通道屏障是否仍然能够正常工作。

通过这些测试,可以验证通道屏障的正确性和效率,以及 sync/barrier 包在实现通道屏障时的正确性和健壮性。同时也可以帮助开发者更好地理解并使用通道屏障这种同步原语。


Structs:

response

在"go/src/runtime/chanbarrier_test.go"文件中,response结构体被用作goroutine之间传递信息的载体。 response结构体包含以下字段:

  1. done:是一个无缓冲的布尔型channel,用于告知调用方协程操作已完成。
  2. pid:表示goroutine的ID(PID)。
  3. val:表示传递的值。

在测试场景中,一个或多个协程通过channel来相互通信。当一个协程完成任务并向另一个协程发送消息时,使用response结构体来携带需要传递的信息。在发送信息之前,需要创建一个响应结构体,并将其发送到通道中。接收方协程通过从通道中读取该结构体来读取相关信息。

总之,response结构体在chanbarrier_test.go文件中扮演着交换协程之间信息的载体的角色。

myError

在go/src/runtime/chanbarrier_test.go文件中,myError结构体被定义为用于模拟错误的类型。因为在测试过程中,经常需要模拟一些出错的情况来验证代码的鲁棒性和正确性,并且在模拟出错的情况时,需要返回一个错误类型的值来表示出错的原因,这时候就可以使用myError结构体来表示一个错误类型。

具体来说,myError结构体实现了error接口,它有一个成员变量errMsg表示错误的描述信息。在使用时,可以通过创建一个myError对象,然后通过将它作为返回值返回给调用方来模拟一个错误的情况。因为myError实现了error接口,所以它也可以作为error类型的值使用,这样可以方便地在测试中使用标准的error处理方法来检测出错情况。

综上所述,myError结构体在测试中扮演着模拟错误的角色,它可以模拟各种类型的错误,方便测试人员编写测试用例,提高代码的鲁棒性和正确性。

Functions:

Error

在go/src/runtime/chanbarrier_test.go文件中,Error函数是用来定制测试结果输出的错误信息的。

在Go语言中,测试代码是通过调用t.Error或t.Errorf函数来报告测试失败的。这个函数会将一个错误信息记录下来,然后测试框架会将这些错误信息进行汇总,并在测试运行结束后输出到控制台。

在chanbarrier_test.go文件中,Error函数的作用就是用来定制输出的错误信息。它接收一个字符串参数,将其作为错误信息记录下来,并在输出时添加一些前缀和后缀,以便更好地区分不同的错误。

例如,Error函数的实现可能如下所示:

func (b *Barrier) Error(msg string) {
    fmt.Printf("Barrier failed: %s\n", msg)
}

这个函数会将传入的错误信息添加一个前缀“Barrier failed: ”,然后输出到控制台。这样做的好处是当测试失败时,我们可以很容易地区分是哪个测试失败了,而且可以看到具体的错误信息,有助于快速定位和解决问题。

doRequest

在 go/src/runtime/chanbarrier_test.go 文件中的 doRequest 函数是一个测试函数,用于测试通道和计数器的并发访问。该函数的作用是通过两个通道来传递请求和响应,以检查循环计数器是否递增。以下是 doRequest 函数的详细介绍:

函数签名:

func doRequest(n int, req, resp chan int, startGate, endGate *sync.WaitGroup)

参数说明:

  • n:表示需要进行的迭代次数
  • req:表示发送请求的通道
  • resp:表示接收响应的通道
  • startGate:表示当所有 goroutine 都准备好时将发送一个信号的同步等待组
  • endGate:表示所有 goroutine 都完成时将发送一个信号的同步等待组

函数实现:

首先,该函数会使用 startGate 等待所有 goroutine 就绪。然后,它将启动一个 for 循环进行 n 次迭代,并在每次迭代中向通道 req 发送请求。然后等待从通道 resp 中接收到响应,然后检查响应是否正确。最后,该函数会使用 endGate 来协调所有的 goroutine,以确保它们都已完成执行。

代码实现:

func doRequest(n int, req, resp chan int, startGate, endGate *sync.WaitGroup) {
    startGate.Done()
    var last int
    for i := 0; i < n; i++ {
        req <- i
        x := <-resp
        if x != last+1 {
            panic("out-of-order response")
        }
        last = x
    }
    endGate.Done()
}

在主函数中,doRequest 函数将作为 goroutine 运行,因此它将并发运行多次。该函数使用两个同步等待组同步所有 goroutine 的开始和结束时间,以确保它们都在正确的时间运行。在并发上下文中,req 和 resp 通道对所有 goroutine 可见,并可用于线程安全的通信。

TestChanSendSelectBarrier

TestChanSendSelectBarrier在ChanBarrier测试组中测试了使用select机制实现的ChanBarrier的发送行为。ChanBarrier旨在在所有goroutine都准备好执行操作之前阻止执行。在这个测试中,我们创建一个长度为goroutine数量的channel,每个goroutine都通过相应的index向此channel发送一个相同的值。接下来,在select中等待所有goroutine都发送后关闭channel,并观察是否完成了所有goroutine的发送。

这个测试确保ChanBarrier在所有goroutine都准备好执行操作之前能够正确地阻止执行,并且确保所有goroutine都能完成发送操作。如果测试通过,则说明ChanBarrier能够正确地实现发送行为。

TestChanSendBarrier

TestChanSendBarrier函数是一个测试函数,用于测试混合使用无缓冲channel和BSP同步(Barriers)时的并发性和正确性。

首先,该函数定义了一个大小为4的slice,里面包含了4个channel,并且随机对它们进行了排序。然后,函数创建了一个sync.WaitGroup实例,用于确保所有goroutine都能够正确退出。

接下来,函数进入一个for循环,创建了4个goroutine,每个goroutine都会调用doSomeWork函数。在doSomeWork函数中,每个goroutine都会向自己分配的channel发送一个随机的字符串。然后,goroutine会尝试从其他3个channel中接收一个字符串。如果其中有一个channel没有数据,它将会等待。

最后,当所有的goroutine都完成了它们的工作时,函数会调用Wait方法等待它们全部完成,确保所有的goroutine都能够正确关闭。最终,通过将4个channel中的4个字符串拼接在一起,检查它们是否等于"0123"来确认测试是否通过。

该函数的主要目的是测试在BSP同步下使用无缓冲channel实现多goroutine并发访问的正确性和效率。在测试中,通过在多个goroutine之间传递数据,测试了无缓冲channel的同步机制和BSP同步的正确性。同时,通过对多个goroutine的并发执行和等待进行测试,也测试了其并发性和可扩展性。

testChanSendBarrier

testChanSendBarrier是一个用于测试goroutine之间通信的函数,它的作用是测试在多个goroutine之间发送数据时的同步机制。

具体来说,该函数在等待所有的goroutine都准备好之后,通过ch的发送操作将数据发送给goroutine。然后,它检查所有的goroutine是否都已经收到了这个数据,如果有任何一个goroutine没有收到,则会引发测试失败。

在这个过程中,testChanSendBarrier使用了两个重要的机制:channel和waitgroup。

  • Channel:在goroutine之间传递数据的管道。testChanSendBarrier函数通过ch这个channel把数据发送给各个goroutine。

  • WaitGroup:它能够跟踪正在运行的所有goroutines,并在所有goroutines都完成后才能进行下一步。通过使用wg来等待所有的goroutine都开始运行之后,通信并同步数据可以确保每个goroutine都处理完了它的任务并且已经接收到了数据。

通过这些机制,testChanSendBarrier可以模拟goroutine之间的通信过程,并确保数据能够在它们之间正确地同步和共享。