zoukankan      html  css  js  c++  java
  • go语言sync包的学习(Mutex、WaitGroup、Cond)

    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    package main;
     
    import (
        "fmt"
        "sync"
        "runtime"
        "time"
    )
     
    //加锁,注意锁要以指针的形式传进来,不然只是拷贝
    func total1(num *int, mu *sync.Mutex, ch chan bool) {
        mu.Lock();
        for i := 0; i < 1000; i++ {
            *num += i;
        }
        ch <- true;
        mu.Unlock();
    }
     
    //不加锁
    func total2(num *int, ch chan bool) {
        for i := 0; i < 1000; i++ {
            *num += i;
        }
        ch <- true;
    }
     
    //Lock、Unlock与RLock、RUnlock不能嵌套使用
    func total3(num *int, rwmu *sync.RWMutex, ch chan bool) {
        for i := 0; i < 1000; i++ {
            rwmu.Lock();
            *num += i;
            rwmu.Unlock();
     
            if(i == 500) {
                //读锁定
                rwmu.RLock();
                fmt.Print(*num, " ");
                rwmu.RUnlock();
            }
        }
        ch <- true;
    }
     
    func printNum(num int, cond *sync.Cond) {
        cond.L.Lock();
        if num < 5 {
            //num小于5时,进入等待状态
            cond.Wait();
        }
        //大于5的正常输出
        fmt.Println(num);
        cond.L.Unlock();
    }
     
    func main() {
        //Once.Do()保证多次调用只执行一次
        once := sync.Once{};
        ch := make(chan bool, 3);
        for i := 0; i < 3; i++ {
            go func(n int) {
                once.Do(func() {
                    //只会执行一次,因为闭包引用了变量n,最后的值为2
                    fmt.Println(n)
                });
                //给chan发送true,表示执行完成
                ch <- true;
            }(i);
        }
        for i := 0; i < 3; i++ {
            //读取三次chan,如果上面三次没执行完会一直阻塞
            <-ch;
        }
     
        //互斥锁,保证某一时刻只能有一个访问对象
        mutex := sync.Mutex{};
        ch2 := make(chan bool, 20);
        //使用多核,不然下面的结果会一样
        runtime.GOMAXPROCS(runtime.NumCPU());
        num1 := 0;
        num2 := 0;
        for i := 0; i < 10; i++ {
            go total1(&num1, &mutex, ch2);
        }
        for i := 0; i < 10; i++ {
            go total2(&num2, ch2);
        }
        for i := 0; i < 20; i++ {
            <-ch2;
        }
        //会发现num1与num2计算出的结果不一样
        //而num1的结果才是正确的,因为total2没有加锁,导致多个goroutine操作num时发生数据混乱
        fmt.Println(num1, num2);
     
        //读写锁,多了读锁定,和读解锁,让多个goroutine同时读取对象
        rwmutex := sync.RWMutex{};
        ch3 := make(chan bool, 10);
        num3 := 0;
        for i := 0; i < 10; i++ {
            go total3(&num3, &rwmutex, ch3);
        }
        for i := 0; i < 10; i++ {
            <-ch3;
        }
        fmt.Println(num3);
     
        //组等待,等待一组goroutine的结束
        wg := sync.WaitGroup{};
        //增加计数器
        wg.Add(10);
        for i:= 0; i< 10; i++ {
            go func(n int) {
                fmt.Print(n, " ");
                //这里表示该goroutine执行完成
                wg.Done();
            }(i);
        }
        //等待所有线程执行完成
        wg.Wait();
     
        fmt.Println("");
     
        //条件等待
        mutex2 := sync.Mutex{};
        //使用锁创建一个条件等待
        cond := sync.NewCond(&mutex2);
     
        for i := 0; i < 10; i++ {
            go printNum(i, cond);
        }
     
        time.Sleep(time.Second * 1);
        //等待一秒后,我们先唤醒一个等待,输出一个数字
        cond.L.Lock()
        cond.Signal();
        cond.L.Unlock();
        time.Sleep(time.Second * 1);
        //再次待待一秒后,唤醒所有,输出余下四个数字
        cond.L.Lock()
        cond.Broadcast();
        cond.L.Unlock();
        time.Sleep(time.Second * 1);
    }
  • 相关阅读:
    Epipe
    手机WiFi万能钥匙查看破解的password和手机查询命令收集
    解决duilib使用zip换肤卡顿的问题(附将资源集成到程序中的操作方法)
    OpenProcess、GetExitCodeProcess、TerminateProcess
    QlikView图表显示同比数据
    系统出现bootmgr is missing解决方式,戴尔dellserver装系统须要特别注意的问题
    导出结果跟查询结果不一致
    MongoDB -- 介绍
    CentOS上编译安装OpenCV-2.3.1与ffmpeg-2.1.2
    js 获取读取cookie
  • 原文地址:https://www.cnblogs.com/ExMan/p/14665207.html
Copyright © 2011-2022 走看看