• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Error

            C++博客 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
              217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks
            先看下boost給的例子,我覺(jué)得有問(wèn)題:

            #include
            <boost/atomic.hpp> class spinlock { private: typedef enum {Locked, Unlocked} LockState; boost::atomic<LockState> state_; public: spinlock() : state_(Unlocked) {} void lock() {
            // 可能這里的boost::memory_order_acquire有原子操作的效果吧,偶不是很理解,不過(guò)我覺(jué)得這里應(yīng)該用cae操作才對(duì) while (state_.exchange(Locked, boost::memory_order_acquire) == Locked) { /* busy-wait */ } } void unlock() {
            // 這里都直接寫(xiě)不做檢查了,更加難以理解 state_.store(Unlocked, boost::memory_order_release); } };

            有可能是我不理解后面的內(nèi)存訪問(wèn)參數(shù)的意義,給下我自己的實(shí)現(xiàn):
            class CESpinLock : boost::noncopyable
            {
            private:
                typedef 
            enum {emUnlocked = 0, emLocked} EM_LockState;

            public:
                CESpinLock() : m_atomicState(emLocked)
                {
                }

            public:
                
            void lock()
                {
                    EM_LockState state 
            = emUnlocked;
                    
            while(false == m_atomicState.compare_exchange_strong(state, emLocked))
                    {
                        state 
            = emUnlocked;
                    }
                }

                
            void unlock()
                {
                    EM_LockState state 
            = emLocked;
                    
            while(false == m_atomicState.compare_exchange_strong(state, emUnlocked))
                    {
                        state 
            = emLocked;
                    }
                }

            private:
                boost::atomic
            <EM_LockState> m_atomicState;
            };


            可以適當(dāng)?shù)脑趂alse里邊加一點(diǎn)sleep操作感覺(jué)。

            還有一點(diǎn)就是不太激烈這里的cae操作分兩種 strong和weak

            bool compare_exchange_weak(T & expected, T desired, memory_order success_order, memory_order failure_order)

            Compare current value with expected, change it to desired if matches. Returns true if an exchange has been performed, and always writes the previous value back in expected. May fail spuriously, so must generally be retried in a loop.

            bool compare_exchange_strong(T & expected, T desired, memory_order order)

            Compare current value with expected, change it to desired if matches. Returns true if an exchange has been performed, and always writes the previous value back in expected

            實(shí)在不理解 May fail spuriously, so must generally be retried in a loop.的意義,不過(guò)看了代碼,在win32的實(shí)現(xiàn)上,weak是調(diào)用了stong實(shí)現(xiàn)的。



             VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:49:07
            atomic的 compare_exchange_weak
            compare_exchange_weak
            有啥區(qū)別

            求解釋
            vczh.Iskandar<vczh@163.com>  21:49:27
            不是一樣嗎
            御虛舟北(314969051)  21:49:40
            改代碼中, ing
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:49:49
            Windows上的實(shí)現(xiàn)是一樣的
            May fail spuriously, so must generally be retried in a loop. 
            這一句怎么理解呢
            vczh.Iskandar<vczh@163.com>  21:50:07
            compare_exchange_weak
            compare_exchange_weak
            質(zhì)量最大vczh粉(402740419)  21:50:14
            compare_exchange_weak
            compare_exchange_weak

            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:50:16
            strong

            compare_exchange_strong
            還有一個(gè)問(wèn)題
            class spinlock {
            private:
              typedef enum {Locked, Unlocked} LockState;
              boost::atomic<LockState> state_;

            public:
              spinlock() : state_(Unlocked) {}

              void lock()
              {
                while (state_.exchange(Locked, boost::memory_order_acquire) == Locked) {
                  /* busy-wait */
                }
              }
              void unlock()
              {
                state_.store(Unlocked, boost::memory_order_release);
              }
            };

            boost例子給的 spinloc
            怎么是這樣實(shí)現(xiàn)的
            都沒(méi)有用cae操作
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:51:20
            unlock都直接用store了
            vczh.Iskandar<vczh@163.com>  21:51:50
            不用compare
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:51:59
             為啥
            無(wú)法理解
            vczh.Iskandar<vczh@163.com>  21:52:34
            想要解釋好麻煩
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:52:40
            還有在Windows上
            boost::memory_order_acquire
            這個(gè)參數(shù)也沒(méi)用
            貌似
            求V神解釋
            還有strong和weak的區(qū)別
            質(zhì)量最大vczh粉(402740419)  21:54:46
            spinlock本來(lái)就不用compare啊
            直接swap就行了
            while (state_.swap(1) == 1);
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:56:24
            你看假設(shè)現(xiàn)在是lock狀態(tài)
            boost的實(shí)現(xiàn)是無(wú)條件吧lock換成unlock
            如果是繼續(xù)lock 他還是lock
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:58:08
            只要要避免 重入吧
            lock之前檢查一下
            御虛舟北(314969051)  22:00:03
            小康你的書(shū)收到?jīng)]有
            質(zhì)量最大vczh粉(402740419)  22:03:17
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  21:58:08
            只要要避免 重入吧
            lock之前檢查一下

            你用錯(cuò)了他不管你
            就是這個(gè)意思
            同一個(gè)線程lock兩次也會(huì)死鎖
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  22:05:05
            原來(lái)是這樣

            但是他lock的時(shí)候不檢查,也會(huì)導(dǎo)致兩個(gè)線程同時(shí)lock吧?
            while (state_.exchange(Locked, boost::memory_order_acquire) == Locked) {
                  /* busy-wait */
                }

            質(zhì)量最大vczh粉(402740419)  22:05:18
            不會(huì)啊
            假設(shè)A進(jìn)程先來(lái)了,lock成功了
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  22:05:33
            怎能理解,我理解和直接賦值是一樣
            我再去看
            質(zhì)量最大vczh粉(402740419)  22:05:40
            這不是復(fù)制
            是exchange
            swap
            另一個(gè)線程exchange就會(huì)收到Locked
            那么另一個(gè)線程就會(huì)while循環(huán),直到原來(lái)線程給設(shè)置了Unlocked
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  22:06:47
            Exchange current value with new_value, returning current value 

            exchange是把新值寫(xiě)入舊值返回么?  不是這樣么?
            我有點(diǎn)理解了
            質(zhì)量最大vczh粉(402740419)  22:07:46
            對(duì)啊,新值寫(xiě)入,舊值返回,原子的
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  22:07:59
            就是說(shuō)寫(xiě)入也是寫(xiě)入的lock, 不影響之前的lock
            當(dāng)前線程拿到舊值檢查是不是lock狀態(tài),如果是就繼續(xù)嘗試直到不是
            質(zhì)量最大vczh粉(402740419)  22:08:00
            所以只會(huì)有一個(gè)線程返回Unlocked,另一個(gè)線程會(huì)收到之前線程設(shè)置的Locked
            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  22:08:11
             受教了
            質(zhì)量最大vczh粉(402740419)  22:08:13

            VCZH.粉絲數(shù)組[0]<errorcpp@qq.com>  22:08:20
            我貼到博客上去 

            posted on 2013-03-31 21:49 Enic 閱讀(3795) 評(píng)論(1)  編輯 收藏 引用 所屬分類: cpp 1x and boost

            評(píng)論

            # re: boost::atomic 實(shí)現(xiàn) spinlock 2013-03-31 23:52 Enic
            老外是這么說(shuō)的:

            http://cbloomrants.blogspot.be/2011/07/07-14-11-compareexchangestrong-vs.html


            07-14-11 - compare_exchange_strong vs compare_exchange_weak

            The C++0x standard was revised a while ago to split compare_exchange (aka CAS) into two ops. A quick note on the difference :

            bool compare_exchange_weak( T * ptr, T * old, T new );

            bool compare_exchange_strong( T * ptr, T * old, T new );

            (BTW in the standard "old" is actually a reference, which is a damn shitty thing to do because it makes it very non-transparent that "old" gets mutated by these functions, so I am showing it as a pointer).
            both try to do :


            atomically {
            if ( *ptr == *old ) { *ptr = new; return true; }
            else { *old = *ptr; return false; }
            }

            the difference is that compare_exchange_weak can also return false for spurious failure. (the original C++0x definition of CAS always allowed spurious failure; the new thing is the _strong version which doesn't).
            If it returns due to spurious failure, then *old might be left untouched (and in fact, *ptr might be equal to *old but we failed anyway).

            If spurious failure can only occur due to contention, then you can still gaurantee progress. In fact in the real world, I believe that LL-SC architectures cannot gaurantee progress, because you can get spurious failure if there is contention anywhere on the cache line, and you need that contention to be specifically on your atomic variable to gaurantee progress. (I guess if you are really worried about this, then you should ensure that atomic variables are padded so they get their own cache line, which is generally good practice for performance reasons anyway).

            On "cache line lock" type architectures like x86, there is no such thing as spurious failure. compare_exchange just maps to "cmpxchg" instruction and you always get the swap that you want. (it can still fail of course, if the value was not equal to the old value, but it will reload old). (BTW it's likely that x86 will move away from this in the future, because it's very expensive for very high core counts)

            compare_exchange_weak exists for LL-SC (load linked/store conditional) type architectures (Power, ARM, basically everything except x86), because on them compare_exchange_strong must be implemented as a loop, while compare_exchange_weak can be non-looping. For example :

            On ARM, compare_exchange_weak is something like :

            compare_exchange_weak:

            ldrex // load with reservation
            teq // test equality
            strexeq // store if equal
            and strexeq can fail for two reasons - either because they weren't equal, or because the reservation was lost (because someone else touched our cache line).
            To implement compare_exchange_strong you need a loop :

            compare_exchange_strong:

            while ( ! compare_exchange_weak(ptr,old,new) ) { }

            (note that you might be tempted to put a (*old = *ptr) inside the loop, but that's probably not a good idea, and not necessary, because compare_exchange_weak will eventually load *ptr into *old itself when it doesn't fail spuriously).
            The funny bit is that when you use compare_exchange you often loop anyway. For example say I want to use compare_exchange_strong to increment a value, I have to do :


            cur = *ptr;
            while( ! compare_exchange_strong(ptr,&cur,cur+1) ) { }

            (note it's a little subtle that this works - when compare_exchange_strong fails, it's because somebody else touched *ptr, so we then reload cur (this is why "old" is passed by address), so you then recompute cur+1 from the new value; so with the compare_exchange_strong, cur has a different value each time around this loop.)
            But on an LL-SC architecture like ARM this becomes a loop on a loop, which is dumb when you could get the same result with a single loop :


            cur = *ptr;
            while( ! compare_exchange_weak(ptr,&cur,cur+1) ) { }

            Note that with this loop now cur does *not* always take a new value each time around the loop (it does when it fails due to contention, but not when it fails just due to reservation-lost), but the end result is the same.
            So that's why compare_exchange_weak exists, but you might ask why compare_exchange_strong exists. If we always use loops like this, then there's no need for it. But we don't always use loops like this, or we might want to loop at the much higher level. For example you might have something like :

            bool SpinLock_TryLock(int * lock)
            {
            int zero = 0;
            return compare_exchange_strong(lock,&zero,1);
            }
            which returns false if it couldn't get the lock (and then might do an OS wait) - you don't want to return false just because of a spurious failure. (that's not a great example, maybe I'll think of a better one later).
            (BTW I think the C++0x stuff is a little bit broken, like most of C standardization, because they are trying to straddle this middle ground of exposing the efficient hardware-specific ways of doing things, but they don't actually expose enough to map directly to the hardware, and they also aren't high level enough to separate you from knowing about the hardware. For example none of their memory model actually maps directly to what x86 provides, therefore there are some very efficient x86-specific ways to do threading ops that cannot be expressed portable in C++0x. Similarly on LL-SC architectures, it would be preferrable to just have access to LL-SC directly.

            I'd rather see things in the standard like "if LL-SC exist on this architecture, then they can be invoked via __ll() and __sc()" ; more generally I wish C had more conditionals built into the language, that would be so much better for real portability, as opposed to the current mess where they pretend that the language is portable but it actually isn't so you have to create your own mess of meta-language through #defines).  回復(fù)  更多評(píng)論
              


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            久久99国内精品自在现线| 久久96国产精品久久久| 亚洲一级Av无码毛片久久精品| 久久久久婷婷| 欧美va久久久噜噜噜久久| 久久精品9988| 亚洲va中文字幕无码久久不卡| 99久久精品国产综合一区| 久久久久亚洲精品日久生情| 久久国产成人精品麻豆| 国内精品综合久久久40p| 99久久99久久精品国产| 丁香色欲久久久久久综合网| 国产A级毛片久久久精品毛片| 亚洲级αV无码毛片久久精品| 婷婷综合久久狠狠色99h| 一本色道久久综合亚洲精品| 国产毛片久久久久久国产毛片| 亚洲精品无码久久久久去q| 精品久久人人爽天天玩人人妻 | 嫩草影院久久国产精品| 伊人久久大香线蕉av不变影院| 久久久久一本毛久久久| 久久久噜噜噜久久熟女AA片| 亚洲乱码日产精品a级毛片久久| 久久青草国产精品一区| 亚洲精品无码久久久影院相关影片| 久久久久亚洲精品无码网址| 99久久婷婷国产综合精品草原| 99久久久精品免费观看国产| 色欲综合久久中文字幕网| 久久www免费人成看片| 无码任你躁久久久久久老妇| 久久精品夜色噜噜亚洲A∨| 99久久国产亚洲高清观看2024| 精品久久久久久久| 久久91亚洲人成电影网站| 欧美一区二区精品久久| 久久婷婷国产麻豆91天堂| 久久r热这里有精品视频| 91精品免费久久久久久久久|