• 记录一个Golang面试编程题目


    开心一刻

           一个国王要替公主征婚,把一个苹果放在公主头上,谁要把它射中就有机会迎娶公主。

           第一个男士把苹果射中,他说:“I’m 罗宾。”

           第二个男士也把苹果射中,他说:“I'm 后羿。”

           第三个男士不小心把公主射死了,他说:“ I'm sorry..."

    题目介绍

           使用两个goroutine交替打印1-100之间的奇数和偶数, 输出时按照从小到大输出.

    做法一

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    func main() {
        ch := make(chan struct{})
        var wg sync.WaitGroup
        wg.Add(2)
        go func() {
            defer wg.Done()
            for i := 1; i < 101; i++ {
                ch <- struct{}{}
                //奇数
                if i%2 == 1 {
                    fmt.Println("线程1打印:",i)
                }
            }
        }()
        go func() {
            defer wg.Done()
            for i := 1; i < 101; i++ {
                <- ch
                //偶数
                if i%2 == 0 {
                    fmt.Println("线程2打印:",i)
                }
            }
        }()
        wg.Wait()
    }
    

    对做法一的理解:
    首先因为变量ch是一个无缓冲的channel, 所以只有读写同时就绪时才不会阻塞。所以两个goroutine会同时进入各自的 if 语句(此时 i 是相同的),但是此时只能有一个 if 是成立的,不管哪个goroutine快,都会由于读channel或写channel导致阻塞,因此程序会交替打印1-100且有顺序。

    做法二

    package main
    
    import (
        "fmt"
        "sync"
    )
    var ch = make(chan struct{})
    var wg sync.WaitGroup
    func go1() {
        defer wg.Done()
        for i := 1; i <= 10; i += 2 {
            fmt.Println(i)
            ch <- struct{}{}//不能与上一行交换位置
            <- ch
        }
    }
    func go2() {
        defer wg.Done()
        for i := 2; i <= 10; i += 2 {
            <- ch
            fmt.Println(i)
            ch <- struct{}{}
        }
    }
    func main() {
        wg.Add(2)
        go go1()
        go go2()
        wg.Wait()
    }
    

    对做法二的理解:
    做法二中两个goroutine分别打印奇数和偶数,在两个goroutine中每次for循环时fmt都能得到执行,所以为了实现交替打印1-100,需要使用两对无缓冲的channel。13行和20行构成第一对同步channel,14和22行构成第二对同步channel,第一对同步channel完成读取数据之前,奇数就已经打印;第二对同步channel完成打印之前,偶数就会打印,所以最终输出就是交替打印1-100

    做法三

    package main
    
    import (
        "fmt"
        "runtime"
        "sync"
    )
    
    func main() {
        //设置可同时使用的CPU核数为1
        var wg sync.WaitGroup
        runtime.GOMAXPROCS(1)
        wg.Add(2)
        go func() {
            defer wg.Done()
            for i := 1; i < 101; i++ {
                //奇数
                if i%2 == 1 {
                    fmt.Println("线程1打印:",i)
                }
                //让出cpu
                runtime.Gosched()
            }
        }()
        go func() {
            defer wg.Done()
            for i := 1; i < 101; i++ {
                //偶数
                if i%2 == 0 {
                    fmt.Println("线程2打印:",i)
                }
                //让出cpu
                runtime.Gosched()
            }
        }()
        wg.Wait()
    }
    

    runtime.Gosched这个函数的作用是让当前goroutine让出CPU,好让其它的goroutine获得执行的机会。同时,当前的goroutine也会在未来的某个时间点继续运行。

    文中都是我个人的理解,如有错误的地方欢迎下方评论告诉我,我及时更正,大家共同进步

  • 相关阅读:
    PwnAuth——一个可以揭露OAuth滥用的利器
    Facebook 被指收集用户数据:通过照片和文本
    avast:中兴手机预装恶意软件 嵌入固件底层
    数字货币钱包安全白皮书
    CVE-2017-8464远程命令执行漏洞(震网漏洞)复现
    南非再曝数据库泄露事件:致百万人信息大白
    华盛顿邮报:FBI 屡次夸大了“手机加密威胁”的数字
    工业互联网联盟发布新物联网安全成熟度模型
    深入剖析最新IE0day漏洞
    联储证券被曝存在多项信息安全漏洞
  • 原文地址:https://www.cnblogs.com/xingyu666/p/14966802.html
Copyright © 2020-2023  润新知