zoukankan      html  css  js  c++  java
  • golang 代码笔记

    互斥锁,g0获取锁,到释放锁之间,g1去获取锁失败,阻塞,g0释放锁之后g1获取锁成功,gn阻塞。

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    func main() {
        //声明
        var mutex sync.Mutex
        fmt.Println("Lock the lock. (G0)")
        //加锁mutex
        mutex.Lock()
    
        fmt.Println("The lock is locked.(G0)")
        for i := 1; i < 4; i++ {
            go func(i int) {
                fmt.Printf("Lock the lock. (G%d)
    ", i)
                mutex.Lock()
                fmt.Printf("The lock is locked. (G%d)
    ", i)
            }(i)
        }
        //休息一会,等待打印结果
        time.Sleep(time.Second)
        fmt.Println("Unlock the lock. (G0)")
        //解锁mutex
        mutex.Unlock()
    
        fmt.Println("The lock is unlocked. (G0)")
        //休息一会,等待打印结果
        time.Sleep(time.Second)
    }
    

    原子操作

    通过atomic的AddUint32方法,只有一个协程可以操作sum,保证结果一定是150,原子操作相当于给sum加了锁。

    package main
    
    import (
        "fmt"
        "sync"
         "sync/atomic"
    )
    
    var m *sync.Mutex
    
    func main() {
        var sum uint32 = 100
        var wg sync.WaitGroup
        for i := 0; i < 50; i++ {
            wg.Add(1)
            go func() {
                defer wg.Done()
                //sum += 1 //1
                atomic.AddUint32(&sum, 1) //2
            }()
        }
        wg.Wait()
        fmt.Println(sum)
    }
    

    go的“any”类型

    类似ts的any,但是很麻烦的是用这个字段的时候需要强转,就是.([]string)这个操作,如果range的时候没把内容转成字符串,就会报错,因为毕竟他是interface{}类型

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        m := map[string]interface{}{
            "Name": "Wednesday",
            "Age":  6,
            "Parents": []string{
                "Gomez",
                "Morticia",
            },
        }
    
        maps := []interface{}{
            "Gomez",
            "Morticia",
        }
        fmt.Println(maps, m)
        for key, value := range m["Parents"].([]string) {
            fmt.Println("Key:", key, "Value:", value)
        }
    }
    

    channel

    go的chan关键字可以创建一个channel用于协程通信, ch <- 是写数据,<- ch是读数据,你也可以用range来读数据,当读不到数据的时候就会阻塞。所以下面的代码不写sleep,go进程也不会退出。

    import (
        "fmt"
        //  "time"
    )
    
    func main() {
        var ch = make(chan []int)
        num := []int{1, 2, 3}
        i := 0
        go func() {
            for {
                ch <- num
                num = append(num, i)
                i++
                fmt.Println("write")
            }
        }()
        for nu := range ch {
            fmt.Println(nu)
        }
    
    }
    

    channel一般都用select来消费,只要一个case成功就完成,不然就阻塞到成功。

    package main
    
    import (
        "time"
        "fmt"
    )
    
    func main(){
        c := make(chan int)
        select{
        case <- c:
            fmt.Println("没有数据")
        case <-time.After(5* time.Second):
            fmt.Println("超时退出")
        }
    }
    

    利用多核cpu

    通过设置runtime.GOMAXPROCS(2),让go协程可以跑在两个cpu上,所以打印的2次0-100,没有先后顺序。go的多核利用是利用多个cpu上跑协程。
    并不是多核一定高效,比如io操作,单核比多核更快,单核没有线程切换的损耗,而且io操作并不需要go来做啥。多核的场景应该是高计算的任务。

    
    import (
        "fmt"
        "runtime"
    )
    
    var quit chan int = make(chan int)
    
    func loop() {
        for i := 0; i < 100; i++ { //为了观察,跑多些
            fmt.Printf("%d ", i)
        }
        quit <- 0
    }
    
    func main() {
        runtime.GOMAXPROCS(2) // 最多使用2个核
    
        go loop()
        go loop()
    
        for i := 0; i < 2; i++ {
            <-quit
        }
    }
    
  • 相关阅读:
    Oracle学习(四)--sql及sql分类讲解
    Oracle学习(三)--数据类型及常用sql语句
    Oracle学习(二)--启动与关闭
    Tomcat学习笔记--启动成功访问报404错误
    有关Transaction not successfully started问题解决办法
    百度富文本编辑器UEditor1.3上传图片附件等
    hibernate+junit测试实体类生成数据库表
    js登录与注册验证
    SVN安装配置与使用
    [LeetCode] #38 Combination Sum
  • 原文地址:https://www.cnblogs.com/dh-dh/p/9219876.html
Copyright © 2011-2022 走看看