默认的 http 那一套,是否保证了原子性? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
mahone3297

默认的 http 那一套,是否保证了原子性?

  •  
  •   mahone3297 2015 年 12 月 2 日 2604 次点击
    这是一个创建于 3797 天前的主题,其中的信息可能已经有所发展或是发生改变。
    上一下代码


    我的疑问:
    1. 我用 ab -c 10 -n 100000 'http://192.168.81.130:8080/increase?key=user&count=1' 去压, server 端,应该是多 go routine 去处理, m 应该是保证不了原子性的吧?但是我的出来的值,却是
    curl 'http://192.168.81.130:8080/debug'
    debug v = map[user:100000]
    很精准的值 100000 。。。测了多次都是。。。
    所以,问题,是这个 http 包保证了?还是 map 保证了?还是其他?
    我是否要用 https://golang.org/pkg/sync/atomic/ 包去保证原子性?

    2. ab 的结果,如下图

    Failed requests: 99991 有这么多 failed ?但是值又都有。这是为什么?
    14 条回复    2015-12-03 10:53:07 +08:00
    9hills
        1
    9hills  
       2015 年 12 月 2 日
    m[key] += 1
    这个最后的累加结果和执行顺序无关,所以累加后的值应该是精确的
    zzn
        2
    zzn  
       2015 年 12 月 2 日
    m 要加锁
    zealot0630
        3
    zealot0630  
       2015 年 12 月 2 日
    go routine 是非抢占的 意味着所有基本操作(非 syscall )都是原子的

    然而,你这个程序冲突概率太低了,即使使用 java/C++这种语言 跑个几天大概能冲突一次吧
    martifact
        4
    martifact  
       2015 年 12 月 2 日
    都不能保证。这个场景下 routine 之间的数据并发应该跟核数有关,概率确实挺低。
    yinheli
        5
    yinheli  
       2015 年 12 月 2 日
    1. 程序执行太快了. 要想模拟冲突, 应该先取出值, 然后随机 sleep 一会, 1 毫秒, 都够
    2. `failed` 是因为你的响应, 不一致. ab 判断长度不同导致的
    fwee
        6
    fwee  
       2015 年 12 月 2 日
    说版本, 1.5 之前默认是单核的协作式,这个结果正常
    raincious
        7
    raincious  
       2015 年 12 月 2 日
    读公共数据的时候需要建立一个 mutex 来锁,否则铁定冲突。

    https://gobyexample.com/mutexes

    想看冲突的话, 1.4 以及之前需要用 runtime.GOMAXPROCS 来使用多个核心。
    raincious
        8
    raincious  
       2015 年 12 月 2 日
    @raincious

    修改,不仅仅是读,写的时候也要锁。详见 Golang 的 Sync 包: https://golang.org/pkg/sync/

    如果只是一个 Int 的话,可以用 Atomic ,我上面帖的例子里也有。但是不知道是不是 atomic 和 mutex 必须结合起来一起用。(我记得只要用 mutex 锁上就好了,不知道记忆是否准确)
    mahone3297
        9
    mahone3297  
    OP
       2015 年 12 月 2 日
    @9hills
    》 m[key] += 1
    》这个最后的累加结果和执行顺序无关,所以累加后的值应该是精确的
    光是这样写,应该也是保证不了原子性的,所以才会有 atomic 库,这个页面中的例子就谈到了这样的情况
    https://golang.org/pkg/sync/atomic/


    @zzn 嗯,应该要加 atomic

    @zealot0630 同上,这个加,应该是非原子的,看下这个库的介绍
    https://golang.org/pkg/sync/atomic/

    @martifact 确实,本来概率就低,我还虚拟机,分配的单核。。。看来环境也有问题


    @yinheli
    》 1. 程序执行太快了. 要想模拟冲突, 应该先取出值, 然后随机 sleep 一会, 1 毫秒, 都够
    确实,说的有道理,考虑试试,谢谢指点。
    2. `failed` 是因为你的响应, 不一致. ab 判断长度不同导致的
    》这个不太明白,再解释下?

    @fwee
    最新版本, 1.5.1

    @raincious
    谢谢例子!好好研究下。
    再问下,我们有些人,第 2 个回复的时候,会 @自己,这有什么好处吗?
    msg7086
        10
    msg7086  
       2015 年 12 月 2 日   1
    @mahone3297 at 自己表示编辑补充,属于惯例用法。
    多数是发现自己上一段没说完整或者没说正确,所以提醒别人下一段是承接、修正上一段的。
    pubby
        11
    pubby  
       2015 年 12 月 2 日
    map 并发读写要上锁,碰到过冲突 panic 的

    另外提一下<map>有意思的地方
    for i,_ := range <map> {
    delete(<map>,i)
    }

    并不会影响 iterator 过程
    pubby
        12
    pubby  
       2015 年 12 月 2 日
    ab 测试的时候,返回的内容长度不同,就会 failed

    你的响应中 %d 只有 1-9 的时候 长度才是一样的,后面都跟第一次不一样,所以全部 failed 了
    mahone3297
        13
    mahone3297  
    OP
       2015 年 12 月 3 日
    @pubby
    >map 并发读写要上锁,碰到过冲突 panic 的
    >另外提一下<map>有意思的地方
    for i,_ := range <map> {
    delete(<map>,i)
    }
    >并不会影响 iterator 过程
    有点意思。。。

    >ab 测试的时候,返回的内容长度不同,就会 failed
    >你的响应中 %d 只有 1-9 的时候 长度才是一样的,后面都跟第一次不一样,所以全部 failed 了
    原来是这样啊。。。了解了。他是要每个请求的返回长度都一样啊。那我这样的案例,如果测试请求是否成功呢?按照 ab 的逻辑,不行了。他干嘛不看返回的 http code 呢,真见鬼。
    pubby
        14
    pubby  
       2015 年 12 月 3 日 via Android
    @mahone3297 可以试试。%010d
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1500 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 60ms UTC 16:49 PVG 00:49 LAX 09:49 JFK 12:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86