游戲策劃咨訊
          做一個游戲并不難,難的是做一個好游戲;完美在于積累!
           

          線程同步和服務(wù)器數(shù)據(jù)保護(hù)

          最近因為自己主持的項目出現(xiàn)些問題,太忙了,所以好久都沒有繼續(xù)寫東西和大家進(jìn)行探討制作開發(fā)部分了。在這一節(jié)中就要向大家介紹另外一個重要的部分,并且也是最頭疼的部分:線程同步和數(shù)據(jù)保護(hù)。

          關(guān)于線程的概念我在前面的章節(jié)中已經(jīng)介紹過了,也就在這里不累贅—“重復(fù)再重復(fù)”了。有一定線程基礎(chǔ)的人都知道,線程只要創(chuàng)建后就如同脫韁的野馬,對于這樣的一匹野馬我們怎么來進(jìn)行控制和處理呢?簡單的說,我們沒有辦法進(jìn)行控制。因為我們更本就沒有辦法知道CPU什么時候來執(zhí)行他們,執(zhí)行他們的次序又是什么?

          有人要問沒有辦法控制那我們?nèi)绾问呛媚兀窟@個問題也正是我這里要向大家進(jìn)行解釋和說明的,雖然我們不能夠控制他們的運行,但我們可以做一些手腳來達(dá)到我們自己的意志。

          這里我們的做手腳也就是對線程進(jìn)行同步,關(guān)于同步的概念大家在《操作系統(tǒng)》中應(yīng)該都看過吧!不了解的話,我簡單說說:讀和寫的關(guān)系(我讀書的時候,請你不要在書上亂寫,否則我就沒有辦法繼續(xù)閱讀了。)

          處理有兩種:用戶方式和內(nèi)核方式。
          用戶方式的線程同步由于有好幾種:原子訪問,關(guān)鍵代碼段等。

          在這里主要向大家介紹關(guān)鍵代碼段的處理(我個人用的比較多,簡單實用)。先介紹一下它的一些函數(shù),隨后提供關(guān)鍵代碼段的處理類供大家參考(比較小,我就直接貼上來了)

          VOID InitializeCriticalSection(    //初始化互斥體
            LPCRITICAL_SECTION lpCriticalSection  // critical section
          );

          VOID DeleteCriticalSection(        //清除互斥體
            LPCRITICAL_SECTION lpCriticalSection   // critical section
          );

          VOID EnterCriticalSection(         //進(jìn)入等待
            LPCRITICAL_SECTION lpCriticalSection  // critical section
          );

          VOID LeaveCriticalSection(         //釋放離開
            LPCRITICAL_SECTION lpCriticalSection   // critical section
          );

          以上就是關(guān)于關(guān)鍵代碼段的基本API了。介紹就不必了(MSDN)。而我的處理類只是將這幾個函數(shù)進(jìn)行了組織,也就是讓大家能夠更加理解關(guān)鍵代碼端
          .h
          class   CCriticalSection                //共享變量區(qū)類
          {
          public:
          CCriticalSection();
          virtual ~CCriticalSection();
          void   Enter();                   //進(jìn)入互斥體
          void   Leave();                  //離開互斥體釋放資源
          private:
             CRITICAL_SECTION  g_CritSect;
          };
          .cpp
          CCriticalSection::CCriticalSection()
          {
          InitializeCriticalSection(&g_CritSect);
          }

          CCriticalSection::~CCriticalSection()
          {
          DeleteCriticalSection(&g_CritSect);
          }

          void  CCriticalSection::Enter()
          {
          EnterCriticalSection(&g_CritSect);
          }

          void  CCriticalSection::Leave()
          {
              LeaveCriticalSection(&g_CritSect);
          }
          由于篇幅有限關(guān)鍵代碼段就說到這里,接下來向大家簡單介紹一下內(nèi)核方式下的同步處理。
          哎呀!這下可就慘了,這可是要說好多的哦!書上的羅羅嗦嗦我就不說了,我就說一些我平時的運用吧。首先內(nèi)核對象和一般的我們使用的對象是不一樣的,這樣的一些對象我們可以簡單理解為特殊對象。而我們內(nèi)核方式的同步就是利用這樣的一些特殊對象進(jìn)行處理我們的同步,其中包括:事件對象,互斥對象,信號量等。對于這些內(nèi)核對象我只向大家說明兩點:
          1.內(nèi)核對象的創(chuàng)建和銷毀
          2.內(nèi)核對象的等待處理和等待副作用

          第一:內(nèi)核對象的創(chuàng)建方式基本上而言都沒有什么太大的差別,例如:創(chuàng)建事件就用HANDLE CreateEvent(…..),創(chuàng)建互斥對象 HANDLE CreateMutex(…….)。而大家注意的也是這三個內(nèi)核對象在創(chuàng)建的過程中是有一定的差異的。對于事件對象我們必須明確指明對象是人工對象還是自動對象,而這種對象的等待處理方式是完全不同的。什么不同下面說(呵呵)。互斥對象比較簡單沒什么說的,信號量我們創(chuàng)建必須注意我們要定義的最大使用數(shù)量和初始化量。最大數(shù)量>初始化量。再有如果我們?yōu)槲覀兊膬?nèi)核對象起名字,我們就可以在整個進(jìn)程中共用,也可以被其他進(jìn)程使用,只需要OPEN就可以了。也就不多說了。

          第二:內(nèi)核對象的等待一般情況下我們使用兩個API:
          DWORD WaitForSingleObject(        //單個內(nèi)核對象的等待
                HANDLE hHandle,        // handle to object
                DWORD dwMilliseconds   // time-out interval
          );

          DWORD WaitForMultipleObjects(     //多個內(nèi)核對象的等待
                DWORD nCount,             // number of handles in array
                CONST HANDLE *lpHandles,  // object-handle array
                BOOL fWaitAll,            // wait option
                DWORD dwMilliseconds      // time-out interval
          );
          具體怎么用查MSDN了。
          具體我們來說等待副作用,主要說事件對象。首先事件對象是分兩種的:人工的,自動的。人工的等待是沒有什么副作用的(也就是說等待成功后,要和其他的對象一樣要進(jìn)行手動釋放)。而自動的就不一樣,但激發(fā)事件后,返回后自動設(shè)置為未激發(fā)狀態(tài)。這樣造成的等待結(jié)果也不一樣,如果有多個線程在進(jìn)行等待事件的話,如果是人工事件,被激活后所有等待線程成執(zhí)行狀態(tài),而自動事件只能有其中一個線程可以返回繼續(xù)執(zhí)行。所以說在使用這些內(nèi)核對象的時候,要充分分析我們的使用目的,再來設(shè)定我們創(chuàng)建時候的初始化。簡單的同步我就說到這里了。下面我就將將我們一般情況下處理游戲服務(wù)器處理過程中的數(shù)據(jù)保護(hù)問題分析:

          首先向大家說說服務(wù)器方面的數(shù)據(jù)保護(hù)的重要性,圖例如下:

          用戶列表

                                            用戶刪除

                                            用戶數(shù)據(jù)修改
                                            
                                            使用數(shù)據(jù)


          加入隊列

          對于上面的圖例大家應(yīng)該也能夠看出在我們的游戲服務(wù)器之中,我們要對于我們用戶的操作是多么的頻繁。如此頻繁的操作我們?nèi)绻贿M(jìn)行處理的話,后果將是悲慘和可怕的,舉例:如果我們在一個線程刪除用戶的一瞬間,有線程在使用,那么我們的錯誤將是不可難以預(yù)料的。我們將用到了錯誤的數(shù)據(jù),可能會導(dǎo)致服務(wù)器崩潰。再者我們多個線程在修改用戶數(shù)據(jù)我們用戶數(shù)據(jù)將是沒有辦法保持正確性的。等等情況都可能發(fā)生。怎么樣杜絕這樣的一些情況的發(fā)生呢?我們就必須要進(jìn)行服務(wù)器數(shù)據(jù)的保護(hù)。而我們?nèi)绾握_的保護(hù)好數(shù)據(jù),才能夠保持服務(wù)器的穩(wěn)定運行呢?下面說一下一些實際處理中的一些經(jīng)驗之談。

          1.我們必須充分的判斷和估計我們服務(wù)器中有那些數(shù)據(jù)要進(jìn)行數(shù)據(jù)保護(hù),這些就需要設(shè)計者和規(guī)劃者要根據(jù)自己的經(jīng)驗進(jìn)行合理的分析。例如:在線用戶信息列表,在線用戶數(shù)據(jù)信息,消息列表等。。。。。

          2.正確和十分小心的保護(hù)數(shù)據(jù)和正確的分析要保護(hù)的數(shù)據(jù)。大家知道我們要在很多地方實現(xiàn)我們的保護(hù)措施,也就是說我們必須非常小心謹(jǐn)慎的來書寫我們的保護(hù),不正確的保護(hù)會造成系統(tǒng)死鎖,服務(wù)器將無法進(jìn)行下去(我在處理的過程中就曾經(jīng)遇到過,頭都大了)。正確的分析要保護(hù)的數(shù)據(jù),也就是說,我們必須要估計到我們要保護(hù)的部分的處理能夠比較快的結(jié)束。否則我們必須要想辦法解決這個問題:例如:
                   
                   DATA_STRUCT  g_data;
                   CRITICAL_SECTION  g_cs;

                   EnterCriticalSection(&g_cs);
                   SendMessage(hWnd,WM_ONEMSG,&g_data,0);
                   LeaveCriticalSection(&g_cs);
          以上處理就有問題了,因為我們不知道SendMessage()什么時候完成,可能是1/1000豪秒,也可能是1000年,那我們其他的線程也就不用活了。所以我們必須改正這種情況。

                   DATA_STRUCT  g_data;
                   CRITICAL_SECTION  g_cs;

                   EnterCriticalSection(&g_cs);
                   PostMessage(hWnd,WM_ONEMSG,&g_data,0);
              LeaveCriticalSection(&g_cs);

          或者        DATA_STRUCT  temp_data;

                   EnterCriticalSection(&g_cs);
                   temp_data = g_cs;
                   LeaveCriticalSection(&g_cs);
                   SendMessage(hWnd,WM_ONEMSG,& temp_data,0);

             3.最好不要復(fù)合保護(hù)用戶數(shù)據(jù),這樣可能會出現(xiàn)一些潛在的死鎖。


          簡而言之,服務(wù)器的用戶數(shù)據(jù)是一定需要進(jìn)行保護(hù),但我們在保護(hù)的過程中就一定需要萬分的小心和謹(jǐn)慎。這篇我就說到這里了,具體的還是需要從實踐中來進(jìn)行學(xué)習(xí),下節(jié)想和大家講講服務(wù)器的場景處理部分。先做事去了。呵呵!!有好的想法和建議的和我交流探討,先謝謝了。

          posted on 2005-02-13 11:54 藍(lán)色雪焰 閱讀(320) 評論(0)  編輯  收藏 所屬分類: 網(wǎng)絡(luò)游戲
           
          主站蜘蛛池模板: 泸溪县| 二连浩特市| 冕宁县| 贵州省| 常宁市| 柳河县| 博野县| 师宗县| 泉州市| 清河县| 浠水县| 汶川县| 安岳县| 乐陵市| 黎城县| 梓潼县| 尖扎县| 东明县| 温宿县| 昭苏县| 门源| 通辽市| 富锦市| 林甸县| 东阿县| 内黄县| 凤阳县| 临猗县| 阿拉善盟| 繁昌县| 邯郸市| 昭苏县| 南城县| 图们市| 迁西县| 漳平市| 阿图什市| 来凤县| 白水县| 皮山县| 东城区|