• <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>
            OnTheWay2012
            埋葬昨天的我,迎來重生的我!
            posts - 15,  comments - 89,  trackbacks - 0
            昨天寫了一篇隨筆,里面提到了單例模式,本來沒有想多說單例模式,可是有人回復說讓我先看看線程安全再來談設計模式。
            今天閑來無事就隨便寫了個線程安全的設計模式,具體代碼如下:
              1#include <iostream>
              2#include <vector>
              3#include <bitset>
              4#include <assert.h>
              5#include <Windows.h>
              6#include <process.h>
              7
              8using namespace std;
              9
             10class CSingleton
             11{
             12private:
             13    class CAssistForSingleton
             14    {
             15    private:
             16        CRITICAL_SECTION m_cs;
             17
             18    public:
             19        CAssistForSingleton()
             20        {
             21            InitializeCriticalSection(&m_cs);
             22        }

             23
             24        ~CAssistForSingleton()
             25        {
             26            DeleteCriticalSection(&m_cs);
             27        }

             28
             29    public:
             30        void Lock()
             31        {
             32            EnterCriticalSection(&m_cs);
             33        }

             34
             35        void UnLock()
             36        {
             37            LeaveCriticalSection(&m_cs);
             38        }

             39    }
            ;
             40
             41private:
             42    static CAssistForSingleton m_refSycObj;
             43    static CSingleton *m_pInstance;
             44
             45    static int m_nData;
             46
             47private:
             48    CSingleton()
             49    {
             50
             51    }

             52
             53public:
             54    static CSingleton *GetInstatnce()
             55    {
             56        m_refSycObj.Lock();
             57        if (NULL == m_pInstance)
             58        {
             59            m_pInstance = new CSingleton;
             60            cout<<"new CSingleton"<<endl;
             61        }

             62        m_refSycObj.UnLock();
             63
             64        return m_pInstance;
             65    }

             66
             67public:
             68    static int GetData() 
             69    {
             70        return m_nData;
             71    }

             72
             73    static void SetData(int nData)
             74    {
             75        m_refSycObj.Lock();
             76        m_nData = nData;
             77        m_refSycObj.UnLock();
             78    }

             79}
            ;
             80
             81CSingleton::CAssistForSingleton CSingleton::m_refSycObj = CSingleton::CAssistForSingleton();
             82CSingleton *CSingleton::m_pInstance = NULL;
             83int CSingleton::m_nData = 0;
             84
             85unsigned int WINAPI ThreadFun(void *)
             86{
             87    cout<<"Launcher Thread"<<endl;
             88    
             89    for(int i = 0 ; i < 99999999 ; i++)
             90    {
             91        CSingleton *pSingl = CSingleton::GetInstatnce();
             92        if (NULL != pSingl)
             93        {
             94            pSingl->SetData(i);
             95        }

             96
             97        Sleep(500);
             98    }

             99
            100    return 0;
            101}

            102
            103int main(int argv, char *argc[])
            104{
            105    uintptr_t HandleThread[10];
            106    unsigned int nThreadId = 0;
            107    for(int i = 0 ; i < 10 ; i++)
            108    {
            109        HandleThread[i] = _beginthreadex(NULL, 0, ThreadFun, NULL, 0&nThreadId);
            110    }

            111
            112    WaitForMultipleObjects(10, (const HANDLE *)HandleThread, TRUE, INFINITE);
            113
            114    return 0;
            115}

            116
            117

            以上就是我的實現,有什么問題歡迎批評指針。
            posted on 2010-05-21 09:52 OnTheWay 閱讀(5748) 評論(15)  編輯 收藏 引用 所屬分類: 軟件設計

            FeedBack:
            # re: 一種線程安全的單例模式實現方式
            2010-05-21 10:15 | 戰魂小筑
            1. 可以不用單件, 程序開始時全局new出來, 以后不用鎖,直接用就好.
            2. 既然全是靜態數據, 還需要用Singleton呢?
            3. 用Interlock會更高效  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-21 10:52 | GunsNRose
            之前看過一個,建議將構造弄成 私有的,生成實例由 GetInstatnce來做
            別人new是new不了的  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-21 15:37 | OwnWaterloo
            依然不是線程安全的。  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-21 21:02 | ccsdu2009
            去看看ZThread中的單件吧

            以前的話我會推薦loki的
            但是現在歸納絕那個太復雜了  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式[未登錄]
            2010-05-22 07:17 | OnTheWay
            @OwnWaterloo
            您好,首先感謝您對本隨筆的關注。懇請您說詳細一點,我不太明白哪些地方還不是線程安全的。  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-22 08:57 | OwnWaterloo
            @OnTheWay
            class S
            {
            S() { ... }
            ~S(); { ... }
            S(S const&);
            S& operator=(S const&S);

            public:
            static S& instance()
            {
            static S s;
            return s;
            }

            };

            你認為C++(C++03)是否保證S::instance是線程安全的?
            如果是, 請說明理由。
            如果C++不保證, 是否應該將S::instance作成線程安全的?
              回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-22 09:00 | OwnWaterloo
            @OnTheWay
            再來一種:

            class S
            {
            // ctor, copy, dtor, assignment
            static S s_;
            public:
            S& instance() { return s_; }
            };

            S S::s_;

            同樣是上面的問題。
              回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式[未登錄]
            2010-05-22 09:12 | OnTheWay
            @OwnWaterloo
            我覺得不是線程安全的,原因如下:
            在你給出的代碼中類S中的函數(雖然現在我還沒有想不出這種函數)可能不是線程安全的。

            我的MSN是wwj_5_209@163.com,能否加我一下,我們討論一下。  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-22 14:59 | 匿名
            @OwnWaterloo
            與博文中的不是一回事。  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-22 19:08 | OwnWaterloo
            @OnTheWay
            注意兩種需要運行時初始化的靜態對象, s和s_。
            前者的初始化時機C++有保證, 但不保證多線程安全。
            后者的初始化時機C++只保證同一翻譯單元內中有順序。

            再看static CAssistForSingleton m_refSycObj;
            這就屬于第2種。

            下面的情況有發生的可能性:
            1. 另一翻譯單元的靜態對象先于m_refSycObj被初始化
            2. 在它初始化時訪問了CSingleton *GetInstatnce()

            此時就訪問了一個"未初始化"的臨界區。
            這已經是bug。

            再有, 如果有下列情況:
            1. 一些先于m_refSycObj初始化的代碼開啟了線程
            2. 多個線程在m_refSycObj初始化前訪問CSingleton *GetInstatnce()

            一個未初始化的m_refSycObj根本不能用于同步。

            所以, 上面的第1個問題: 這樣做不是多線程安全的。


            而靜態對象在構造時啟動線程的情況并不多, 所以并不一定需要將s_作成多線程安全。
            例如boost就是這樣, 要求在進入main之前, 是不許有兩條以上的執行路徑去訪問。
            這就是第2個問題。


            如果需要完全的多線程安全:
            1. 使用once_initial函數(pthread或者win6有提供)
            2. 使用"可以靜態初始化"的鎖, 比如pthread_mutex_t就可以
            或者自己使用一個spinlock也行。

            我沒有msn…… 用gmail的同名郵箱。
              回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-22 19:09 | OwnWaterloo
            @匿名
            知道什么叫"舉一反三"嗎?
              回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式[未登錄]
            2010-05-22 22:50 | ~
            個人一點隨想:我覺得應該從實際應用的邏輯上來進行線程安全的分析,并根據現實情況的分析避免不必要的加解鎖操作。某些代碼只是一種理想化的東西。現實中有太多比SetData復雜的邏輯。而且也不一定需要加鎖。當然從你這個代碼看,GetInstatnce當然是正確的哈。  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-05-27 00:02 | GunsNRose
            傻逼實現也好意思貼出來?丟人現眼  回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式[未登錄]
            2010-05-27 08:56 | cppexplore
            @OnTheWay
            c++里的線程安全單例應該是典型的雙重檢測.
            文中如此實現的話, 每次調用GetInstatnce都要涉及到加鎖操作, 估計沒人愿意調用.   回復  更多評論
              
            # re: 一種線程安全的單例模式實現方式
            2010-10-30 14:27 | 楊云召
            沒有用volatile,顯然不是線程安全的  回復  更多評論
              

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            友情連接

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            免费久久人人爽人人爽av| 久久最新免费视频| 天天爽天天狠久久久综合麻豆| 久久婷婷色综合一区二区| 色综合久久久久久久久五月| 久久久久人妻一区精品色| 丁香狠狠色婷婷久久综合| 久久精品国产精品亚洲人人| 久久午夜福利电影| 久久精品无码专区免费东京热| 久久久久综合网久久| 亚洲精品第一综合99久久| 蜜臀av性久久久久蜜臀aⅴ麻豆| 99久久国产综合精品麻豆| 久久人人爽人人爽人人片AV麻豆 | 久久久久亚洲AV成人片| 久久福利青草精品资源站| 香蕉久久夜色精品国产2020| 777米奇久久最新地址| 亚洲国产精品无码久久青草| 久久AV无码精品人妻糸列| 国产免费久久精品丫丫| 久久永久免费人妻精品下载| 久久久久婷婷| 久久er热视频在这里精品| 99蜜桃臀久久久欧美精品网站| 伊人色综合久久天天| 久久精品中文闷骚内射| 亚洲成色WWW久久网站| 亚洲欧美久久久久9999| 久久精品国产72国产精福利| 国产欧美久久一区二区| 久久99精品久久久大学生| 一级a性色生活片久久无少妇一级婬片免费放| 久久综合给久久狠狠97色| 久久成人小视频| 国产一区二区久久久| 伊人 久久 精品| 国产精品亚洲综合久久 | 久久国产精品久久久| 亚洲色大成网站WWW久久九九|