English 中文(简体)
翻新方案——共同变量的出现
原标题:C Threaded Programming - Incrementing a shared variable
  • 时间:2009-10-07 18:34:42
  •  标签:

Hey guys...so I m试图冲上我的C楼,我发现的一个问题是:

鉴于全球变量x = 0;执行功能真空无用(int n),该功能产生线形状,在 lo状增加×1时,每read在X达到100时终止。

我只靠read子处理,需要一个牢固的榜样来奠定我的基础。 这必须尽可能使用校对系统。

最佳回答

首先,你们需要决定你们想要达到什么目标,不同路面的指令可以如何避免出现这种情况。

Cx<>x的增量操作者通常被采用为从记忆到登记册的价值;增加登记册;写记:

    r1 ← xglobal
    r1 ← r1 + 1
    xglobal ← r1

因此,x全球的价值被一加一。

如果你同时有两条read子,那么他们就会受到毁灭性干扰。

    initial xglobal = 99

    r1 ← xglobal     
    compare r1 100 
                    r2 ← xglobal          
                    compare r2 100 
    r1 ← r1 + 1  == 100 
                    r2 ← r2 + 1 == 100
    xglobal ← r1    == 100
                    xglobal ← r2     == 100
    r1 ← xglobal     
    compare r1 100 
    stop
                    r2 ← xglobal     
                    compare r1 100 
                    stop
    final xglobal = 100

因此,x全球值被一加一,尽管二者都read了。

(我略去说明ach具的影响,这意味着阅读2版的变数时,即使正好一字的书写在墙壁上读之前发生,也可能发生。) 寻找和释放胎面中的mut子,造成记忆障碍,迫使所有人在行为发生后和书写行为,就像在取得或释放之前发生。 iii

(以上为for(t r; r = x ) < 100;x = r + 1 ),而不是for(;x < 100;x = x + 1 ),后者可读到x,因此,还有另一个点,read可以干预......)

同样,一对一线的加固可摧毁另一条透镜的加固,使胎面与i <相平;100:

    initial xglobal = 98
                    r2 ← xglobal          
    r1 ← xglobal     
    compare r1 100 
    r1 ← r1 + 1  == 99
    xglobal ← r1     
    r1 ← xglobal     
    compare r1 100 
    r1 ← r1 + 1  == 100
    xglobal ← r1     
    r1 ← xglobal     
    compare r1 100 
    stop
                    compare r2 100 
                    r2 ← r2 + 1 == 99
                    xglobal ← r2      
                    ...
    final xglobal = 99

因此,左胎表面的第二次加热,在第一次加热时已经过时,而且会以全球可见的x <值终止;100。

你们可能知道这一切,并可能希望利用一种机制来防止这种情况。

我可以说,你的要求是明确的——在X达到100时,上文的线索即告终止;这些要求并没有说它这样做。

因此,由于没有书面Xglobal ← 100,实际上可以在不设锁的情况下满足这一要求,但<代码>x<>>>>x 可加添<>n*100倍而不是100倍。 (如果该限额大于按部就班,则X的书写在某些平台上可能不会进行分类,如果来自不同透镜的tes合在一起,可能会造成一种无限的 lo,但只有100的宽度达到一定点。)

一种技术是使用mutex ,其中把其他透镜从一对read在路面上锁时停下来。 如果在x全球<>之前获得这一锁,在x全球<><<><><><><<><<>>>书面之前不予以发放,那么该read的读本和写便不可相互分离。

    initial xglobal = 98

    lock (mutex) 
    mutex locked 
                    lock(mutex) 
                    blocked 
    r1 ← xglobal     
    compare r1 100 
    r1 ← r1 + 1  == 99
    xglobal ← r1     

    release ( mutex )
                    mutex locked

                    r2 ← xglobal          
                    compare r2 100 
                    r2 ← r2 + 1 == 100
                    xglobal ← r2      

                    release ( mutex )

    lock (mutex) 
    mutex locked 
    r1 ← xglobal     
    compare r1 100 
    release ( mutex )
    stop
                    ...
    final xglobal = 100

在校外,您不妨利用平台的比较和互换操作(_sync_val_compare_and_swap in gcc ),该平台处理旧价值和新价值,并在新价值相同的情况下将原有记忆与新价值挂钩。 这让你把逻辑写成:

for ( int v = 0; v < 100; ) {
    int x_prev = __sync_val_compare_and_swap ( &x, v, v + 1 );

    // if the CAS succeeds, the value of x has been set to is x_prev + 1
    // otherwise, try again from current last value
    if ( x_prev == v ) 
        v = x_prev + 1;
    else
        v = x_prev;
}

因此

    initial xglobal = 98
    initial v1  = 0
    initial v2  = 0

    cmp v1  100
    x_prev1 ← CASV ( xglobal, v1, v1 + 1 ) = 98 ( set fails with x == 98 )

                    cmp v2  100
                    x_prev2 ← CASV ( xglobal, v1, v1 + 1 ) = 98 ( set fails with x == 98 )

    v1 ← x_prev1 = 98 // x_prev != v
                    v2 ← x_prev2 = 98
                    cmp v2  100
                    x_prev2 ← CASV ( xglobal, v1, v1 + 1 ) = 98 ( set succeeds with x == 99 )

                    v2 ← x_prev2 + 1 = 99 // as x_prev == v

    cmp v1  100
    x_prev1 ← CASV ( xglobal, v1, v1 + 1 ) = 99 ( set fails with x == 99 )
    v1 ← x_prev1 = 99 // as x_prev != v

    cmp v1  100
    x_prev1 ← CASV ( xglobal, v1, v1 + 1 ) = 99 ( set succeeds with x == 100)
    v1 ← x_prev1 + 1 = 100 // as x_prev == v

                    cmp v2  100
                    x_prev2 ← CASV ( xglobal, v1, v1 + 1 ) = 100 ( set fails with x == 100 )

                    v2 ← x_prev2  = 100 // as x_prev != v
    cmp v1  100
                    cmp v2  100
    stop
                    stop

每一次休息室,xglobalatomically 如果并且只有在其先前的价值为1>+1>时,才将其数值定为<>/sub>;如果没有,则将“1> = 化学文摘社登记系统运行期间测试的xglobal数值。 这减少了大多数执行阶段的锁定时间(尽管在化学文摘社运行期间仍需要锁定记忆公共汽车,但只有这些行动将进行序列化。 由于在多个核心领域执行化学文摘社费用昂贵,因此,这种简单案例可能胜诉。 iii

问题回答

You need a mutex to protect the variable. Each thread will lock the mutex, increment the variable and release the mutex. Each thread that doesn t do this is a rogue thread.

我认为,如果“X >”能为每一条read子出走,则“InterlockIncrement”就足够了。

我永远不会使用一个关键部分,除非我确实不得不这样做,因为这可能导致大量争论。 洲际水泥公司根本不存在争议,至少不会影响所有业绩。





相关问题