9.并发

来源:互联网 发布:手机玩gta5的软件 编辑:程序博客网 时间:2024/06/06 14:28

1.并发
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述


2.goroutine

package mainimport (    "fmt"    "runtime"    "sync")func main() {    // 分配一个逻辑处理器给调度器使用    runtime.GOMAXPROCS(1)    // wg 用来等待程序完成    // 计数加 2,表示要等待两个goroutine    //WaitGroup 是一个计数信号量,可以用来记录并维护运行的goroutine。如果WaitGroup    //的值大于0,Wait 方法就会阻塞    var wg sync.WaitGroup    wg.Add(2)    fmt.Println("Start Goroutines")    // 声明一个匿名函数,并创建一个goroutine    go func() {        // 在函数退出时调用Done 来通知main 函数工作已经完成        defer wg.Done()        for count := 0; count < 3; count++ {            for char := 'a'; char < 'a' + 26; char++ {                fmt.Printf(" %c ",char)            }        }    }()    go func() {        defer wg.Done()        for count := 0; count < 3; count++ {            for char := 'A'; char < 'A' + 26; char++ {                fmt.Printf(" %c ",char)            }        }    }()    // 等待 goroutine 结束    fmt.Println("Waiting To Finish")    wg.Wait()    fmt.Println("\nTetmination Programing")}

这里写图片描述

go build -race 程序名  // 调试并发

3.锁住共享资源

package mainimport (    "fmt"    "runtime"    "sync"    "sync/atomic")var (    conter int64  // counter 是所有goroutine 都要增加其值的变量    wg sync.WaitGroup // wg 用来等待程序结束)func main() {    // 计数加 2,表示要等待两个goroutine    wg.Add(2)    // 计数加 2,表示要等待两个goroutine    go incCounter(1)    go incCounter(2)    // 等待 goroutine 结束    wg.Wait()    fmt.Println("Final Counter : ",conter)}// incCounter 增加包里counter 变量的值func incCounter(id int) {    // 在函数退出时调用Done 来通知main 函数工作已经完成    defer wg.Done()    for count := 0; count < 2; count++ {        // 在函数退出时调用Done 来通知main 函数工作已经完成        atomic.AddInt64(&conter,1)        // 当前 goroutine 从线程退出,并放回到队列        runtime.Gosched()    }}

这里写图片描述

package mainimport (    "fmt"    "sync"    "sync/atomic"    "time")var (    shutdown int64    wg sync.WaitGroup)func main() {    wg.Add(2)    go doWork("A")    go doWork("B")    time.Sleep(1 * time.Second)    fmt.Println("Shutdown Now")    // 该停止工作了,安全地设置shutdown 标志    atomic.StoreInt64(&shutdown,1)    wg.Wait()}func doWork(name string) {    defer wg.Done()    for {        fmt.Printf("Doing %s Work\n",name)        time.Sleep(250 * time.Millisecond)        // 检测之前的shutdown 标志来决定是否提前终止        // 要停止工作了吗?        if atomic.LoadInt64(&shutdown) == 1 {            fmt.Printf("Shutting %s Down\n",name)            break        }    }}

这里写图片描述


4.互斥锁

package mainimport (    "fmt"    "runtime"    "sync")var (    counter int    wg sync.WaitGroup    mutex sync.Mutex)func main() {    wg.Add(2)    go incCounter(1)    go incCounter(2)    wg.Wait()    fmt.Printf("Final Counter : %d\n",counter)}// incCounter 使用互斥锁来同步并保证安全访问func incCounter(id int) {    // 在函数退出时调用Done 来通知main 函数工作已经完成    defer wg.Done()    // 同一时刻只允许一个goroutine 进入    // 这个临界区    for count := 0; count < 2; count++ {        mutex.Lock()        {            // 捕获 counter 的值            value := counter            // 当前 goroutine 从线程退出,并放回到队列            runtime.Gosched()            // 增加本地 value 变量的值            value++            // 将该值保存回counter            counter = value        }        // 释放锁,允许其他正在等待的goroutine        mutex.Unlock()    }}

这里写图片描述


5.通道
这里写图片描述
这里写图片描述

package mainimport (    "fmt")func main() {    // 有缓冲的字符串通道,包含一个10 个值的缓冲区    buffer := make(chan string, 10)    // 通过通道发送一个字符串    buffer <- "Goper"    // 从通道接收一个字符串    value := <-buffer    fmt.Println(value)}

无缓冲的通道:
这里写图片描述
这里写图片描述
这里写图片描述

package mainimport (    "fmt"    "math/rand"    "sync"    "time")// wg 用来等待程序结束var wg sync.WaitGroupfunc init() {    rand.Seed(time.Now().UnixNano())}func main() {    // 创建一个无缓冲的通道    court := make(chan int)    // 计数加 2,表示要等待两个goroutine    wg.Add(2)    // 启动两个选手    go palyer("Nadal",court)    go palyer("Djokovic",court)    // 发球    court <- 1    // 等待游戏结束    wg.Wait()}// player 模拟一个选手在打网球func palyer(name string,court chan int) {    // 在函数退出时调用Done 来通知main 函数工作已经完成    defer wg.Done()    for {        // 等待球被击打过来        ball, ok := <- court        if !ok {            // 等待球被击打过来            fmt.Printf("Player %s Won\n",name)            return        }        // 选随机数,然后用这个数来判断我们是否丢球        n := rand.Intn(100)        if  n%13 == 0 {            fmt.Printf("Player %s Missed\n",name)            // 关闭通道,表示我们输了            close(court)            return        }        // 显示击球数,并将击球数加1        fmt.Printf("Player %s Hit %d \n",name,ball)        ball++        // 将球打向对手        court <- ball    }}

这里写图片描述
这里写图片描述

package mainimport (    "fmt"    "sync"    "time")var wg sync.WaitGroupfunc main() {    // 创建一个无缓冲的通道    baton := make(chan int)    // 为最后一位跑步者将计数加1    wg.Add(1)    // 第一位跑步者持有接力棒    go Runner(baton)    // 开始比赛    baton <- 1    // 等待比赛结束    wg.Wait()}// Runner 模拟接力比赛中的一位跑步者func Runner(baton chan int) {    var newRunner int    // 等待接力棒    runner := <- baton    // 开始绕着跑道跑步    fmt.Printf("Runner %d Running with Baton \n",runner)    // 创建下一位跑步者    if runner != 4 {        newRunner = runner + 1        fmt.Printf("Runner %d to the lien\n",newRunner)        go Runner(baton)    }    // 围绕跑道跑    time.Sleep(100 * time.Millisecond)    // 比赛结束了吗?    if runner == 4 {        fmt.Printf("Runner %d Finish \n",runner)        wg.Done()        return    }    // 将接力棒交给下一位跑步者    fmt.Printf("Runner %d Exchange With Runner %d\n",    runner,    newRunner)    baton <- newRunner}

这里写图片描述
这里写图片描述

有缓冲的通道:
这里写图片描述
这里写图片描述

package mainimport (    "fmt"    "math/rand"    "sync"    "time")const (    // 要使用的goroutine 的数量    numberGoroutens = 4    // 要处理的工作的数量    taskLoad = 10)// wg 用来等待程序完成var wg sync.WaitGroup// init 初始化包,Go 语言运行时会在其他代码执行之前,优先执行这个函数func init() {    // 初始化随机数种子    rand.Seed(time.Now().Unix())}func main() {    // 创建一个有缓冲的通道来管理工作    tasks := make(chan string,taskLoad)    // 启动 goroutine 来处理工作    wg.Add(numberGoroutens)    for gr := 1; gr <= numberGoroutens; gr++ {        go worker(tasks, gr)    }    // 增加一组要完成的工作    for post := 1; post <= taskLoad; post++ {        tasks <- fmt.Sprintf("Task : %d",post)    }    // 当所有工作都处理完时关闭通道,以便所有goroutine 退出    close(tasks)    // 等待所有工作完成    wg.Wait()}//worker 作为goroutine 启动来处理,从有缓冲的通道传入的工作func worker(tasks chan string,worker int) {    // 通知函数已经返回    defer wg.Done()    for {        // 等待分配工作        task, ok := <- tasks        if !ok {            // 这意味着通道已经空了,并且已被关闭            fmt.Printf("Worker : %d : Shutting down \n",worker)            return        }        // 显示我们开始工作了        fmt.Printf("Worker :%d : Startig %s\n",worker,task)        // 随机等一段时间来模拟工作        sleep := rand.Int63n(100)        time.Sleep(time.Duration(sleep)*time.Millisecond)        // 显示我们完成了工作        fmt.Printf("Worker : %d : Complete %s \n",worker,task)    }}

这里写图片描述
这里写图片描述

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝原单退回运费怎么办 运输过程中包裹破损怎么办 天猫没收到货签收怎么办 收到的快递坏了怎么办 自寄的快递少了怎么办 邮的东西弄坏了怎么办 物流签收后发现货物损坏怎么办 发现客人损坏了酒店物品怎么办 东西坏了签收了怎么办 朋友圈贩卖三无产品你怎么办 付钱给微商没有保障怎么办 电镀锌钢带生锈怎么办 电机机油从空气滤芯里流出怎么办 把塑料皮套吃了怎么办 塑料框眼镜有点小了怎么办 出口纸箱打了钉怎么办 买房子交款单据丢了怎么办 买房子所有单据丢失怎么办 车险单据都丢了怎么办 真空包装的东西里面有空气怎么办 发货物忘记写唛头了怎么办 Word文档撤销按钮删除了怎么办 ai保存时未响应怎么办 ai还没保存卡了怎么办 ai卡住了没保存怎么办 屁股沟有硬块红肿怎么办 卧室床选太大了怎么办 画板的笔尖掉了怎么办 宜家水壶盖子有水怎么办 背滤鱼缸除油膜怎么办 书多了没地方放怎么办 学生在教室内丢手机怎么办 新车尾箱坏了怎么办 放书的箱子烂了怎么办 车钥匙锁后备箱里怎么办 布的收纳箱有味怎么办 车漆清漆层掉了怎么办 副驾驶储物箱卡子断了怎么办 玛莎拉蒂车门打不开怎么办 新买的水杯漏水怎么办 泰迪小狗掉毛怎么办