作者回复: 对,所以注释中才会那么说。
作者回复: 对,这就是传指针值的好处之一。
作者回复: 再说一遍,Go语言里没有深层复制。数组是值类型,所以会被完全复制。
作者回复: 第一个问题,长度代表通道当前包含的元素个数,容量就是初始化时你设置的那个数。
第二个问题你再想想,可以做做试验。
作者回复: 环形链表
作者回复: 其实都是浅表复制。数组因为是值类型的,所以即使是浅复制也能完全复制过来。
作者回复: 你理解的没错,在同一时刻,只有一个goroutine能够对某一个通道进行取出操作,其他的试图对这个通道进行取出操作的goroutine都会被阻塞,并进入通道内部的队列排队。通道会保证这种操作是互斥的,并且是原子性的(完全取走一个元素值之后,下一个元素值才有可能被取)。
我回答那位同学的意思是:两个go函数中的代码是有可能同时(在同一个很小的时间段内)执行到“取出操作”那一行代码的。不过我们完全不用在意,因为通道和运行时系统会保证这类操作的并发安全。
可能我那个回答太短了吧,咱俩没有对上口径。
作者回复: 需要手动关闭,这是个很好的习惯,而且也可以利用关的动作来给接收方传递一个信号。Go的GC只会清理被分配到堆上的、不再有任何引用的对象。
作者回复: 原则上可以传任何类型的数据。不过,要是传指针的话要自己保证安全啊,原始数据放篡改之类的。
作者回复: 它是面向同一个进程的。多个进程之间内存一般不会共享,所以没法用channel。进程间通讯可以考虑IPC方法,比如有名管道,你可以参看一下os.Pipe函数的文档。其实进程间通讯最强大和灵活的还是socket。
作者回复: 浅拷贝只是拷贝值以及值中直接包含的东西,深拷贝就是把所有深层次的结构一并拷贝。
作者回复: 好,收到。
作者回复: 为什么非要知道那些 goroutine 都是第几个呢?再说了,你那个 NowTotal 中的
for i:=0;i<s.now;i++ {
s.nowtotal<-i
}
相当于向 nowtotal 发送 0、1、2、3、4、5、6、7、8、9。那你的 Wait 方法每次给 total 赋的值就是不一样的。即使你的 if total == s.now-1 可以判断已经够 10 个 goroutine了,可 s.chanArr<-i 不应该是最后一个 Wait 方法做的事。你想想,你这样只能完成一次“阻塞 9 个,满 10 个放行”。
我觉得你实现得不好。职责划分不清晰。你应该将把控的逻辑放在 NowTotal 方法里。Wait 方法每执行一次就通过通道告诉 NowTotal 一下。告诉完了,Wait 方法用另一个通道阻塞自己。一旦够了 10 个,NowTotal 就通过第二个通道放行。
作者回复: 所以说不要用“协程”这个概念,因为“协程(coroutine)”指的是程序在同一个线程内的自行调度,是应用程序本身完全可控的。而 goroutine 的调度是 Go 语言的运行时系统发起的。
你不要揣测 Go 语言的调度器会怎样调度。你首先要知道哪些代码点是调度的时机(注意,到了调度时机也不一定发生调度,只是时机而已)。你还要知道如果想让多个 goroutine 按照你拟定的流程执行就需要用到 Channel 以及各种同步工具。
你说的“跳转到”只能在 coroutine 场景下才能这么说。在 goroutine 的场景下,没有“跳转”这么一说。
其一,你在上面的 for 语句中启用了一个 goroutine,你怎么就能断定后面的代码一定会先于这个 go 函数执行?不要做这种假设。因为连 goroutine 的调度都是并发的。
其二,两个 goroutine 一个 channel,一个 goroutine 发,一个 goroutine 取。这个 ch1 什么时候满、什么时候空,你基本上是确定不了的。因为两个 for 循环 在迭代的过程中都可能因被调用而换下 CPU。
其三,你要知道,几乎任何函数调用都存在调度时机,更何况是像 fmt.Println 这种需要 I/O 的重型操作。所以,为什么你那前一个 for 循环结束之后就不能被调度了呢?
以上是我通过你的文字表达猜测并回答的,并不一定完全匹配你要问的问题。还有问题的话再问我。
我觉得你对“并发”和“调度”这两个概念不清楚。我建议你好好看看专栏里讲 goroutine 的那几篇文章。有必要的话,买我的《Go 并发编程实战》第二版从头学一下。
作者回复: 问题很明显啊,怎么能用 for sign == 0 呢?两个问题,一个是你不能假定 go 函数(这里是 send 函数)的执行时机。另一个是你这样使用 sign 变量不是并发安全的,产生了竞态条件。用你的 stateChan 做状态传递多好。
作者回复: 如果你的通道要给外人使用,或者通过通道对外提供功能,那就不要传指针值了,容易造成安全漏洞,另外这个时候最好限制下通道的方向。