并发编程这块断断续续看了挺久的,&感觉还是有地方没有理解。有时间还是要找找正式的代码看一看,不然不知道怎么用啊。
有些地方不清楚该怎么用,所以下面写的有些乱,再有新的理解再进行补充。。。
// GoStudy0228 project main.go /* go语言学习——并发编程 go语言中支持轻量级线程goroutine go语言中以消息机制作为通信方式 */ package main import ( "fmt" "sync" "time" ) func main() { //程序从这开始执行 v1 := make(chan [2]int) //定义chan,这里的chan用来传递一个大小为2的int数组 v2 := [2]int{1, 2} //定义数组 var v3 chan bool = make(chan bool, 10) //另一种定义chan的方式,后面的10,是缓存空间的大小,缓存区在被填满的时候是阻塞的 go Add(v1, v3) //go关键字启动goroutine v1 <- v2 //将v2传入chan,在goroutine没有创建的时候,不能向v1传值。 var v4 bool = <-v3 //这里进行阻塞,直到Add函数向chan中传入值以后才能够继续运行。不然可能goroutine没有执行完,main就已经执行完了。 fmt.Println(v4) //可以将Add函数的isFinished去掉,然后运行看结果,就知道为什么要额外加一个chan了 v6 := make(chan int, 10) timeOut := make(chan bool) go TimeWait(timeOut) //一种超时处理方式,但目前没有理解号怎么用 select { //类似于switch,但是只能用于IO方面 case <-v6: // fmt.Println("从v6读取数据") break case <-timeOut: fmt.Println("超时") break default: // fmt.Println("+++++++++++") } //------------------------------ //单向chan的创建 //v21 := make(chan int, 1024) //基于v21创建单向chan //v22 := <-chan int(v21) //只读 //v23 := chan<- int(v21) //只写 close(v1) //关闭管道v1 _, ok1 := <-v1 fmt.Println("v1 is open?", ok1) //------------------------------ //同步锁 //var v31 sync.Mutex int//单一读写 //var v32 sync.RWMutex float32//单写多读 //v31.Lock()//锁定和解锁要对应,否则死锁卡死 //defer v31.Unlock()//这个函数崩溃的时候执行这句,解除锁定 //v32.RLock() //defer v32.RUnlock() //------------------------------ var v41 sync.Once //全局唯一,多个调用的时候,会阻塞,一个执行完才进行下一个 v41.Do(func() { fmt.Println("Hello World!!") }) } //程序运行到这退出 func Add(ch chan [2]int, isFinished chan bool) { nums := <-ch //chan被读取前,这里是阻塞的 for i := 0; i < 100; i++ { fmt.Println("NO.", i, ":", nums[0]+nums[1]) } isFinished <- true } func TimeWait(isFinished chan bool) { //等待函数 time.Sleep(1) //等待一秒 isFinished <- true } /* 几种多线程的方式 1.多进程,操作系统层面,开销大 2.多线程,系统层面,使用最多,最有效,开销较大,高并发对性能有影响 3.基于回掉的非阻塞/异步IO,通过事件驱动方式使用异步IO,尽可能少用线程,降低开销,但编程比多线程要复杂 4.协程,有效解决高并发问题,系统开销极小,编程简单,结构清晰,但是需要语言支持(或者用户自行拓展) */ /* 线程间通信:共享内存模式,消息传递模式 */
//:)