青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 200, comments - 8, trackbacks - 0, articles - 0

2015年1月13日

     摘要: 1    背景    12    Volatile:易變的    12.1    小結(jié)    23    Volatil...  閱讀全文

posted @ 2015-01-13 20:35 鑫龍 閱讀(441) | 評論 (0)編輯 收藏

2014年9月29日

     摘要: 轉(zhuǎn)自:http://my.oschina.net/moooofly/blog/175019最近看 GLib 的代碼遇到這個東東,網(wǎng)上搜索一圈,發(fā)現(xiàn)很多人都寫過這個,自己今天才研究到,汗顏一下,掃盲一個點,留此記錄為證! 首先看一篇最官方的講解: ====== likely() and unlikely() What are they ?       In Linux ...  閱讀全文

posted @ 2014-09-29 21:31 鑫龍 閱讀(7734) | 評論 (0)編輯 收藏

2014年9月23日

一、linux下安裝cmake

首先下載源碼包
        http://www.cmake.org/cmake/resources/software.html

        這里下載的是cmake-2.8.9.tar.gz

隨便找個目錄解壓縮

1         tar -xzvf cmake-2.8.9.tar.gz
2         cd cmake-cmake-2.8.9

        依次執(zhí)行:

1         ./bootstrap
2          make
3         make install

        cmake 會默認(rèn)安裝在 /usr/local/bin 下面

要改變安裝路徑,在bootstrap命令中加入'--prefix=PATH'選項。


二、linux下安裝boost
linux平臺下要編譯安裝除gcc和gcc-c++之外,還需要兩個開發(fā)庫:bzip2-devel 和python-devel,因此在安裝前應(yīng)該先保證這兩個庫已經(jīng)安裝:

#yum install gcc gcc-c++ bzip2 bzip2-devel bzip2-libs python-devel -y

然后是去官網(wǎng)下載源碼包,地址
下載,解壓,按照如下步驟:

#tar xvzf boost_1_50_0.tar.gz

進(jìn)入boost_1_50_0目錄:

#cd boost_1_50_0

然后是編譯安裝,boost源碼包中有配置腳本,直接用就可以:

#sh ./bootstrap.sh

Building Boost.Build engine with toolset gcc... tools/build/v2/engine/bin.linuxx86_64/b2
Detecting Python version... 2.6
Detecting Python root... /usr
Unicode/ICU support for Boost.Regex?... not found.
Generating Boost.Build configuration in project-config.jam...

Bootstrapping is done. To build, run:

./b2

To adjust configuration, edit 'project-config.jam'.
Further information:

- Command line help:
./b2 --help

- Getting started guide:
http://www.boost.org/more/getting_started/unix-variants.html

- Boost.Build documentation:
http://www.boost.org/boost-build2/doc/html/index.html

接下來就是編譯,重點關(guān)注是否編譯成功:

#./b2

然后就是漫長的等待,如果最后出現(xiàn):

The Boost C++ Libraries were successfully built!

The following directory should be added to compiler include paths:

/home/gang/BAK/boost_1_50_0

The following directory should be added to linker library paths:

/home/gang/BAK/boost_1_50_0/stage/lib

表示編譯成功,如果沒有成功,就需要回查看哪里出現(xiàn)error,再安裝相應(yīng)的庫,
最后就是安裝:

#./b2 install --prefix=/usr/local

安裝后的頭文件在/usr/local/include/boost里面,而相應(yīng)的庫在/usr/local/lib/libboost_*

posted @ 2014-09-23 09:29 鑫龍 閱讀(1101) | 評論 (0)編輯 收藏

2014年9月17日

轉(zhuǎn)自:http://www.cnblogs.com/jiqing9006/archive/2012/09/11/2679831.html

冒泡事件就是點擊子節(jié)點,會向上觸發(fā)父節(jié)點,祖先節(jié)點的點擊事件。

下面是html代碼部分:

<body>
<div id="content">
    外層div元素
    <span>內(nèi)層span元素</span>
    外層div元素
</div>

<div id="msg"></div>
</body>

對應(yīng)的jQuery代碼如下:

<script type="text/javascript">
$(function(){
    // 為span元素綁定click事件
    $('span').bind("click",function(){
        var txt = $('#msg').html() + "<p>內(nèi)層span元素被點擊.<p/>";//獲取html信息
        $('#msg').html(txt);// 設(shè)置html信息
    });
    // 為div元素綁定click事件
    $('#content').bind("click",function(){
        var txt = $('#msg').html() + "<p>外層div元素被點擊.<p/>";
        $('#msg').html(txt);
    });
    // 為body元素綁定click事件
    $("body").bind("click",function(){
        var txt = $('#msg').html() + "<p>body元素被點擊.<p/>";
        $('#msg').html(txt);
    });
})
</script>

當(dāng)點擊span時,會觸發(fā)div與body 的點擊事件。點擊div時會觸發(fā)body的點擊事件。

如何防止這種冒泡事件發(fā)生呢?

修改如下:

<script type="text/javascript">
$(function(){
       // 為span元素綁定click事件
    $('span').bind("click",function(event){
        var txt = $('#msg').html() + "<p>內(nèi)層span元素被點擊.<p/>";
        $('#msg').html(txt);
        event.stopPropagation();    //  阻止事件冒泡
    });
    // 為div元素綁定click事件
    $('#content').bind("click",function(event){
        var txt = $('#msg').html() + "<p>外層div元素被點擊.<p/>";
        $('#msg').html(txt);
        event.stopPropagation();    //  阻止事件冒泡
    });
    // 為body元素綁定click事件
    $("body").bind("click",function(){
        var txt = $('#msg').html() + "<p>body元素被點擊.<p/>";
        $('#msg').html(txt);
    });
})
</script>

event.stopPropagation(); // 阻止事件冒泡

 

有時候點擊提交按鈕會有一些默認(rèn)事件。比如跳轉(zhuǎn)到別的界面。但是如果沒有通過驗證的話,就不應(yīng)該跳轉(zhuǎn)。這時候可以通過設(shè)置event.preventDefault(); //阻止默認(rèn)行為 ( 表單提交 )。

下面是案例:

<script type="text/javascript">
$(function(){
   $("#sub").bind("click",function(event){
         var username = $("#username").val();  //獲取元素的值,val() 方法返回或設(shè)置被選元素的值。
         if(username==""){     //判斷值是否為空
             $("#msg").html("<p>文本框的值不能為空.</p>");  //提示信息
             event.preventDefault();  //阻止默認(rèn)行為 ( 表單提交 )
         }
   })
})
</script>

html部分:

<body>
<form action="test.html">
用戶名:<input type="text" id="username" />
<br/>
<input type="submit" value="提交" id="sub"/>
</form>

<div id="msg"></div>
</body>

還有一種防止默認(rèn)行為的方法就是return false。效果一樣。

代碼如下:

<script type="text/javascript">
$(function(){
   $("#sub").bind("click",function(event){
         var username = $("#username").val();  //獲取元素的值
         if(username==""){     //判斷值是否為空
             $("#msg").html("<p>文本框的值不能為空.</p>");  //提示信息
             return false;
         }
   })
})
</script>

同理,上面的冒泡事件也可以通過return false來處理。

<script type="text/javascript">
$(function(){
       // 為span元素綁定click事件
    $('span').bind("click",function(event){
        var txt = $('#msg').html() + "<p>內(nèi)層span元素被點擊.<p/>";
        $('#msg').html(txt);
        return false;
    });
    // 為div元素綁定click事件
    $('#content').bind("click",function(event){
        var txt = $('#msg').html() + "<p>外層div元素被點擊.<p/>";
        $('#msg').html(txt);
        return false;
    });
    // 為body元素綁定click事件
    $("body").bind("click",function(){
        var txt = $('#msg').html() + "<p>body元素被點擊.<p/>";
        $('#msg').html(txt);
    });
})
</script>

posted @ 2014-09-17 14:22 鑫龍 閱讀(292) | 評論 (0)編輯 收藏

2014年9月12日

轉(zhuǎn)自:http://www.cnblogs.com/jiayy/p/3246167.html

在看多核編程相關(guān)論文時,往往一個并發(fā)算法會說自己是wait-free的或者lock-free的,或者是 non-blocking 的,這些專有詞匯其實表示的是并發(fā)的程度,或者說并發(fā)的級別。并發(fā)級別的理解是閱讀各種并發(fā)算法設(shè)計論文以及并發(fā)數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的必備基礎(chǔ)。

1.1  Wait-freedom 無等待并發(fā)

Wait-freedom 指的是每一個線程都一直運(yùn)行下去而無須等待外部條件,整個流程中任何操作都能在一個有限的步驟內(nèi)完成,這是最高的并發(fā)級別,沒有任何阻塞。

 結(jié)合之前原子操作部分的知識,可以簡單認(rèn)為能夠直接調(diào)用一個原子操作實現(xiàn)的算法或程序就屬于Wait-free,比如下面的 increment_reference_counter 函數(shù)就是wait-free的,它封裝了atomic_increment這個原子自增原語,多個線程可以同時調(diào)用這個函數(shù)對同一個內(nèi)存變量進(jìn)行自增,而無須任何阻塞(其實也是有阻塞的,是總線鎖級別)

 與此做對比,CAS類的調(diào)用就不是wait-free的,注意wait-free的原語都不能包含內(nèi)部循環(huán),CAS原語使用時通常包含在“循環(huán)直到成功”的循環(huán)內(nèi)部。

 void increment_reference_counter(rc_base* obj)

{

    atomic_increment(obj->rc);

}

1.2  Lock-freedom 無鎖并發(fā)

Lock-freedom 指的是整個系統(tǒng)作為一個整體一直運(yùn)行下去,系統(tǒng)內(nèi)部單個線程某段時間內(nèi)可能會饑餓,這是比wait-freedom弱的并發(fā)級別,但系統(tǒng)整體上看依然是沒有阻塞的。所有wait-free的算法顯然都滿足lock-free的要求。

 Lock-free算法通常可以通過同步原語 CAS實現(xiàn)。

 void stack_push(stack* s, node* n)

{

    node* head;

    do

    {

        head = s->head;

        n->next = head;

    }

    while ( ! atomic_compare_exchange(s->head, head, n));

}

多個線程同時調(diào)用上述函數(shù),理論上某個線程可以一直困在循環(huán)內(nèi)部,但一旦有一個線程原子操作失敗而返回循環(huán),意味著有其他線程成功執(zhí)行了原子操作而退出循環(huán),從而保證系統(tǒng)整體是沒有阻塞的。

 其實前面的原子自增函數(shù)也可以用下面的原語實現(xiàn),在這種實現(xiàn)里,不再是所有線程都無阻塞了,某些線程可能會因為CAS失敗而回繞若干次循環(huán)。

void increment_reference_counter(rc_base* obj)

{

       Int rc;

       Do {

       rc = obj->rc;

} while(!atomic_compare_exchange(obj->rc,rc,rc+1));

}

1.3  Obstruction-freedom 無阻塞并發(fā)

Obstruction-free 是指在任何時間點,一個孤立運(yùn)行線程的每一個操作可以在有限步之內(nèi)結(jié)束。只要沒有競爭,線程就可以持續(xù)運(yùn)行,一旦共享數(shù)據(jù)被修改,Obstruction-free 要求中止已經(jīng)完成的部分操作,并進(jìn)行回滾,obstruction-free 是并發(fā)級別更低的非阻塞并發(fā),該算法在不出現(xiàn)沖突性操作的情況下提供單線程式的執(zhí)行進(jìn)度保證,所有 Lock-Free 的算法都是 Obstruction-free 的。

1.4  Blocking algoithms 阻塞并發(fā)

阻塞類的算法是并發(fā)級別最低的同步算法,它一般需要產(chǎn)生阻塞??梢院唵握J(rèn)為基于鎖的實現(xiàn)是blocking的算法。詳細(xì)參考第五章

上述幾種并發(fā)級別可以使用下圖描述:
藍(lán)色是阻塞的算法,綠色是非阻塞算法,金字塔越上方,并發(fā)級別越高,性能越好,右邊的金字塔是實現(xiàn)工具(原子操作、鎖、互斥體等)

posted @ 2014-09-12 13:05 鑫龍 閱讀(434) | 評論 (0)編輯 收藏

2014年9月3日

轉(zhuǎn)自:http://www.isnowfy.com/understand-to-lock-free/

以前一直不明白lock free是什么,后來發(fā)現(xiàn)原來是完全理解錯了概念,lock free看到大家有的翻譯為無鎖,有的翻譯為鎖無關(guān),其實用不用鎖和lock free是不相關(guān)的,用了鎖也可能是lock free,而不用鎖有可能不是lock free。

一個lock free的解釋是

一個“鎖無關(guān)”的程序能夠確保執(zhí)行它的所有線程中至少有一個能夠繼續(xù)往下執(zhí)行。

其實看我們那副圖就是說你的各個線程不會互相阻塞,那么你的程序才能成為lock free的。像我們平常用的互斥鎖,當(dāng)有線程獲得鎖,其他線程就被阻塞掉了,這里的問題就是如果獲得鎖的線程掛掉了,而且鎖也沒有釋放,那么整個程序其實就被block在那了,而如果程序是lock free的那么即使有線程掛掉,也不影響整個程序繼續(xù)向下進(jìn)行,也就是系統(tǒng)在整體上而言是一直前進(jìn)的。

那么,不用鎖就是lock free的嗎,一開始就提到了,不用鎖也可能不是lock free的,舉個例子

  1. while (x == 0) {
  2.     x = 1-x;
  3. }

在這里如果兩個線程同時執(zhí)行,可能同時進(jìn)入while循環(huán),然后x兩次改變值之后,依然是0,那么兩個線程就會一直互相在這里阻塞掉了,所以這里雖然沒有鎖,依然不是lock free的。

現(xiàn)在大家寫lock free的時候一般都會使用CAS(compare and set)操作來寫,因為現(xiàn)在很多的cpu都是支持CAS操作并作為原子操作來處理的,CAS操作一般是這樣的

  1. bool compare_and_swap (int *oldval, int *dest, int newval) {
  2.   if (*oldval == *dest) {
  3.       *dest = newval;
  4.       return true;
  5.   }
  6.   return false;
  7. }

其實這樣一個操作和樂觀鎖很像,并且操作簡單,相應(yīng)的比互斥鎖的代價要小。所以現(xiàn)在大家都是喜歡用lock free的技術(shù)來提高系統(tǒng)的performance。

最后如果大家對于如何編寫lock free的數(shù)據(jù)結(jié)構(gòu)感興趣的話,可以參考我后面給出的鏈接。

一種高效無鎖內(nèi)存隊列的實現(xiàn)
無鎖隊列的實現(xiàn)
鎖無關(guān)的(Lock-Free)數(shù)據(jù)結(jié)構(gòu)
An Introduction to Lock-Free Programming

posted @ 2014-09-03 21:11 鑫龍 閱讀(3252) | 評論 (0)編輯 收藏

2014年8月23日

轉(zhuǎn)自:http://zhucuicui.96986.blog.163.com/blog/static/5833370220136219016445/

建立socket后默認(rèn)connect()函數(shù)為阻塞連接狀態(tài),在大多數(shù)實現(xiàn)中,connect的超時時間在75s至幾分鐘之間,想要縮短超時時間,可解決問題的兩種方法:方法一、將socket句柄設(shè)置為非阻塞狀態(tài),方法二、采用信號處理函數(shù)設(shè)置阻塞超時控制。

在一個TCP套接口被設(shè)置為非阻塞之后調(diào)用connect,connect會立即返回EINPROGRESS錯誤,表示連接操作正在進(jìn)行中,但是仍未完成;同時TCP的三路握手操作繼續(xù)進(jìn)行;在這之后,我們可以調(diào)用select來檢查這個鏈接是否建立成功;非阻塞connect有三種用途:
1.我們可以在三路握手的同時做一些其它的處理.connect操作要花一個往返時間完成,而且可以是在任何地方,從幾個毫秒的局域網(wǎng)到幾百毫秒或幾秒的廣域網(wǎng).在這段時間內(nèi)我們可能有一些其他的處理想要執(zhí)行;
2.可以用這種技術(shù)同時建立多個連接.在Web瀏覽器中很普遍;
3.由于我們使用select來等待連接的完成,因此我們可以給select設(shè)置一個時間限制,從而縮短connect的超時時間.在大多數(shù)實現(xiàn)中,connect的超時時間在75秒到幾分鐘之間.有時候應(yīng)用程序想要一個更短的超時時間,使用非阻塞connect就是一種方法;
非阻塞connect聽起來雖然簡單,但是仍然有一些細(xì)節(jié)問題要處理:
1.即使套接口是非阻塞的,如果連接的服務(wù)器在同一臺主機(jī)上,那么在調(diào)用connect建立連接時,連接通常會立即建立成功.我們必須處理這種情況;
2.源自Berkeley的實現(xiàn)(和Posix.1g)有兩條與select和非阻塞IO相關(guān)的規(guī)則:
A:當(dāng)連接建立成功時,套接口描述符變成可寫;
B:當(dāng)連接出錯時,套接口描述符變成既可讀又可寫;
注意:當(dāng)一個套接口出錯時,它會被select調(diào)用標(biāo)記為既可讀又可寫;

非阻塞connect有這么多好處,但是處理非阻塞connect時會遇到很多可移植性問題;

處理非阻塞connect的步驟:
第一步:創(chuàng)建socket,返回套接口描述符;
第二步:調(diào)用fcntl把套接口描述符設(shè)置成非阻塞;
第三步:調(diào)用connect開始建立連接;
第四步:判斷連接是否成功建立;
A:如果connect返回0,表示連接簡稱成功(服務(wù)器可客戶端在同一臺機(jī)器上時就有可能發(fā)生這種情況);
B:調(diào)用select來等待連接建立成功完成;
如果select返回0,則表示建立連接超時;我們返回超時錯誤給用戶,同時關(guān)閉連接,以防止三路握手操作繼續(xù)進(jìn)行下去;
如果select返回大于0的值,則需要檢查套接口描述符是否可讀或可寫;如果套接口描述符可讀或可寫,則我們可以通過調(diào)用getsockopt來得到套接口上待處理的錯誤(SO_ERROR),如果連接建立成功,這個錯誤值將是0,如果建立連接時遇到錯誤,則這個值是連接錯誤所對應(yīng)的errno值(比如:ECONNREFUSED,ETIMEDOUT等).
"讀取套接口上的錯誤"是遇到的第一個可移植性問題;如果出現(xiàn)問題,getsockopt源自Berkeley的實現(xiàn)是返回0,等待處理的錯誤在變量errno中返回;但是Solaris會讓getsockopt返回-1,errno置為待處理的錯誤;我們對這兩種情況都要處理;

這樣,在處理非阻塞connect時,在不同的套接口實現(xiàn)的平臺中存在的移植性問題,首先,有可能在調(diào)用select之前,連接就已經(jīng)建立成功,而且對方的數(shù)據(jù)已經(jīng)到來.在這種情況下,連接成功時套接口將既可讀又可寫.這和連接失敗時是一樣的.這個時候我們還得通過getsockopt來讀取錯誤值;這是第二個可移植性問題;
移植性問題總結(jié):
1.對于出錯的套接口描述符,getsockopt的返回值源自Berkeley的實現(xiàn)是返回0,待處理的錯誤值存儲在errno中;而源自Solaris的實現(xiàn)是返回0,待處理的錯誤存儲在errno中;(套接口描述符出錯時調(diào)用getsockopt的返回值不可移植)
2.有可能在調(diào)用select之前,連接就已經(jīng)建立成功,而且對方的數(shù)據(jù)已經(jīng)到來,在這種情況下,套接口描述符是既可讀又可寫;這與套接口描述符出錯時是一樣的;(怎樣判斷連接是否建立成功的條件不可移植)

這樣的話,在我們判斷連接是否建立成功的條件不唯一時,我們可以有以下的方法來解決這個問題:
1.調(diào)用getpeername代替getsockopt.如果調(diào)用getpeername失敗,getpeername返回ENOTCONN,表示連接建立失敗,我們必須以SO_ERROR調(diào)用getsockopt得到套接口描述符上的待處理錯誤;
2.調(diào)用read,讀取長度為0字節(jié)的數(shù)據(jù).如果read調(diào)用失敗,則表示連接建立失敗,而且read返回的errno指明了連接失敗的原因.如果連接建立成功,read應(yīng)該返回0;
3.再調(diào)用一次connect.它應(yīng)該失敗,如果錯誤errno是EISCONN,就表示套接口已經(jīng)建立,而且第一次連接是成功的;否則,連接就是失敗的;

被中斷的connect:
如果在一個阻塞式套接口上調(diào)用connect,在TCP的三路握手操作完成之前被中斷了,比如說,被捕獲的信號中斷,將會發(fā)生什么呢?假定connect不會自動重啟,它將返回EINTR.那么,這個時候,我們就不能再調(diào)用connect等待連接建立完成了,如果再次調(diào)用connect來等待連接建立完成的話,connect將會返回錯誤值EADDRINUSE.在這種情況下,應(yīng)該做的是調(diào)用select,就像在非阻塞式connect中所做的一樣.然后,select在連接建立成功(使套接口描述符可寫)或連接建立失敗(使套接口描述符既可讀又可寫)時返回;

方法二、定義信號處理函數(shù):

 

  1. sigset(SIGALRM, u_alarm_handler);
  2. alarm(2);
  3. code = connect(socket_fd, (struct sockaddr*)&socket_st, sizeof(struct sockaddr_in));
  4. alarm(0);
  5. sigrelse(SIGALRM);

首先定義一個中斷信號處理函數(shù)u_alarm_handler,用于超時后的報警處理,然后定義一個2秒的定時器,執(zhí)行connect,當(dāng)系統(tǒng)connect成功,則系統(tǒng)正常執(zhí)行下去;如果connect不成功阻塞在這里,則超過定義的2秒后,系統(tǒng)會產(chǎn)生一個信號,觸發(fā)執(zhí)行u_alarm_handler函數(shù), 當(dāng)執(zhí)行完u_alarm_handler后,程序?qū)⒗^續(xù)從connect的下面一行執(zhí)行下去。
其中,處理函數(shù)可以如下定義,也可以加入更多的錯誤處理。

  1. void u_alarm_handler()
  2. {
  3. }

posted @ 2014-08-23 17:01 鑫龍 閱讀(1671) | 評論 (0)編輯 收藏

2014年8月7日

引用:http://m.shnenglu.com/isware/archive/2011/07/20/151470.aspx
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
“據(jù)說”驚群問題已經(jīng)是一個很古老的問題了,并且在大多數(shù)系統(tǒng)中已經(jīng)得到有效解決,但對我來說,仍舊是一個比較新的概念,因此有必要記錄一下。

什么是驚群

        舉一個很簡單的例子,當(dāng)你往一群鴿子中間扔一塊食物,雖然最終只有一個鴿子搶到食物,但所有鴿子都會被驚動來爭奪,沒有搶到食物的鴿子只好回去繼續(xù)睡覺, 等待下一塊食物到來。這樣,每扔一塊食物,都會驚動所有的鴿子,即為驚群。對于操作系統(tǒng)來說,多個進(jìn)程/線程在等待同一資源是,也會產(chǎn)生類似的效果,其結(jié) 果就是每當(dāng)資源可用,所有的進(jìn)程/線程都來競爭資源,造成的后果:
1)系統(tǒng)對用戶進(jìn)程/線程頻繁的做無效的調(diào)度、上下文切換,系統(tǒng)系能大打折扣。
2)為了確保只有一個線程得到資源,用戶必須對資源操作進(jìn)行加鎖保護(hù),進(jìn)一步加大了系統(tǒng)開銷。

        最常見的例子就是對于socket描述符的accept操作,當(dāng)多個用戶進(jìn)程/線程監(jiān)聽在同一個端口上時,由于實際只可能accept一次,因此就會產(chǎn)生驚群現(xiàn)象,當(dāng)然前面已經(jīng)說過了,這個問題是一個古老的問題,新的操作系統(tǒng)內(nèi)核已經(jīng)解決了這一問題。

linux內(nèi)核解決驚群問題的方法

        對于一些已知的驚群問題,內(nèi)核開發(fā)者增加了一個“互斥等待”選項。一個互斥等待的行為與睡眠基本類似,主要的不同點在于:
        1)當(dāng)一個等待隊列入口有 WQ_FLAG_EXCLUSEVE 標(biāo)志置位, 它被添加到等待隊列的尾部. 沒有這個標(biāo)志的入口項, 相反, 添加到開始.
        2)當(dāng) wake_up 被在一個等待隊列上調(diào)用時, 它在喚醒第一個有 WQ_FLAG_EXCLUSIVE 標(biāo)志的進(jìn)程后停止。
        也就是說,對于互斥等待的行為,比如如對一個listen后的socket描述符,多線程阻塞accept時,系統(tǒng)內(nèi)核只會喚醒所有正在等待此時間的隊列 的第一個,隊列中的其他人則繼續(xù)等待下一次事件的發(fā)生,這樣就避免的多個線程同時監(jiān)聽同一個socket描述符時的驚群問題。

根據(jù)以上背景信息,我們來比較一下常見的Server端設(shè)計方案。
方案1:listen后,啟動多個線程(進(jìn)程),對此socket進(jìn)行監(jiān)聽(僅阻塞accept方式不驚群)。
方案2:主線程負(fù)責(zé)監(jiān)聽,通過線程池方式處理連接。(通常的方法)
方案3:主線程負(fù)責(zé)監(jiān)聽,客戶端連接上來后由主線程分配實際的端口,客戶端根據(jù)此端口重新連接,然后處理數(shù)據(jù)。

先考慮客戶端單連接的情況
方案1:每當(dāng)有新的連接到來時,系統(tǒng)內(nèi)核會從隊列中以FIFO的方式選擇一個監(jiān)聽線程來服務(wù)此連接,因此可以充分發(fā)揮系統(tǒng)的系能并且多線程負(fù)載均衡。對于單連接的場景,這種方案無疑是非常優(yōu)越的。遺憾的是,對于select、epoll,內(nèi)核目前無法解決驚群問題。(nginx對于驚群問題的解決方法)
方案2:由于只有一個線程在監(jiān)聽,其瞬時的并發(fā)處理連接請求的能力必然不如多線程。同時,需要對線程池做調(diào)度管理,必然涉及資源共享訪問,相對于方案一來說管理成本要增加不少,代碼復(fù)雜度提高,性能也有所下降。
方案3:與方案2有不少類似的地方,其優(yōu)勢是不需要做線程調(diào)度。缺點是增加了主線程的負(fù)擔(dān),除了接收連接外還需要發(fā)送數(shù)據(jù),而且需要兩次連接,孰優(yōu)孰劣,有待測試。

再考慮客戶端多連接的情況:
對于數(shù)據(jù)傳輸類的應(yīng)用,為了充分利用帶寬,往往會開啟多個連接來傳輸數(shù)據(jù),連接之間的數(shù)據(jù)有相互依賴性,因此Server端要想很好的維護(hù)這種依賴性,把同一個客戶端的所有連接放在一個線程中處理是非常有必要的。
A、同一客戶端在一個線程中處理
方案1:如果沒有更底層的解決方案的話,Server則需要維護(hù)一個全局列表,來記錄當(dāng)前連接請求該由哪個線程處理。多線程需要同時競爭一個全局資源,似乎有些不妙。
方案2:主線程負(fù)責(zé)監(jiān)聽并分發(fā),因此與單連接相比沒有帶來額外的性能開銷。僅僅會造成主線程忙于更多的連接請求。
方案3:較單線程來說,主線程工作量沒有任何增加,由于多連接而造成的額外開銷由實際工作線程分擔(dān),因此對于這種場景,方案3似乎是最佳選擇。

B、同一客戶端在不同線程中處理
方案1:同樣需要競爭資源。
方案2:沒理由。
方案3:不可能。

另外:
(《UNIX網(wǎng)絡(luò)編程》第三版是在第30章)
讀《UNIX網(wǎng)絡(luò)編程》第二版的第一卷時,發(fā)現(xiàn)作者在第27章“客戶-服務(wù)器程序其它設(shè)計方法”中的27.6節(jié)“TCP預(yù)先派生子進(jìn)程服務(wù)器程序,accept無上鎖保護(hù)”中提到了一種由子進(jìn)程去競爭客戶端連接的設(shè)計方法,用偽碼描述如下:

服務(wù)器主進(jìn)程:

listen_fd = socket(...);
bind(listen_fd, ...);
listen(listen_fd, ...);
pre_fork_children(...);
close(listen_fd);
wait_children_die(...);


服務(wù)器服務(wù)子進(jìn)程:

while (1) {
conn_fd = accept(listen_fd, ...);
do_service(conn_fd, ...);
}


初識上述代碼,真有眼前一亮的感覺,也正如作者所說,以上代碼確實很少見(反正我讀此書之前是確實沒見過)。作者真是構(gòu)思精巧,巧妙地繞過了常見的預(yù)先創(chuàng)建 子進(jìn)程的多進(jìn)程服務(wù)器當(dāng)主服務(wù)進(jìn)程接收到新的連接必須想辦法將這個連接傳遞給服務(wù)子進(jìn)程的“陷阱”,上述代碼通過共享的傾聽套接字,由子進(jìn)程主動地去向內(nèi) 核“索要”連接套接字,從而避免了用UNIX域套接字傳遞文件描述符的“淫技”。

不過,當(dāng)接著往下讀的時候,作者談到了“驚群” (Thundering herd)問題。所謂的“驚群”就是,當(dāng)很多進(jìn)程都阻塞在accept系統(tǒng)調(diào)用的時候,即使只有一個新的連接達(dá)到,內(nèi)核也會喚醒所有阻塞在accept上 的進(jìn)程,這將給系統(tǒng)帶來非常大的“震顫”,降低系統(tǒng)性能。

除了這個問題,accept還必須是原子操作。為此,作者在接下來的27.7節(jié)講述了加了互斥鎖的版本:

while (1) {
lock(...);
conn_fd = accept(listen_fd, ...);
unlock(...);
do_service(conn_fd, ...);
}


原子操作的問題算是解決了,那么“驚群”呢?文中只是提到在Solaris系統(tǒng)上當(dāng)子進(jìn)程數(shù)由75變成90后,CPU時間顯著增加,并且作者認(rèn)為這是因為進(jìn) 程過多,導(dǎo)致內(nèi)存互換。對“驚群”問題回答地十分含糊。通過比較書中圖27.2的第4列和第7列的內(nèi)容,我們可以肯定“真兇”絕對不是“內(nèi)存對換”。

“元兇”到底是誰?

仔細(xì)分析一下,加鎖真的有助于“驚群”問題么?不錯,確實在同一時間只有一個子進(jìn)程在調(diào)用accept,其它子進(jìn)程都阻塞在了lock語句,但是,當(dāng) accept返回并unlock之后呢?unlock肯定是要喚醒阻塞在這個鎖上的進(jìn)程的,不過誰都沒有規(guī)定是喚醒一個還是喚醒多個。所以,潛在的“驚 群”問題還是存在,只不過換了個地方,換了個形式。而造成Solaris性能驟降的“罪魁禍?zhǔn)?#8221;很有可能就是“驚群”問題。

崩潰了!這么說所有的鎖都有可能產(chǎn)生驚群問題了?

似乎真的是這樣,所以減少鎖的使用很重要。特別是在競爭比較激烈的地方。

作者在27.9節(jié)所實現(xiàn)的“傳遞文件描述符”版本的服務(wù)器就有效地克服了“驚群”問題,在現(xiàn)實的服務(wù)器實現(xiàn)中,最常用的也是此節(jié)所提到的基于“分配”形式。

把“競爭”換成“分配”是避免“驚群”問題的有效方法,但是也不要忽視“分配”的“均衡”問題,不然后果可能更加嚴(yán)重哦!

posted @ 2014-08-07 14:21 鑫龍 閱讀(575) | 評論 (0)編輯 收藏

2014年7月25日

程序設(shè)計類
《C++ PRIMER》
《STL源碼解析》


系統(tǒng)編程類
《UNIX環(huán)境高級編程》W.Richard Stevens:非常經(jīng)典的書。雖然初學(xué)者就可以看,但是事實上它是《Unix Network Programing》的一本輔助資料。國內(nèi)的翻譯的《UNIX環(huán)境高級編程》的水平不怎么樣,現(xiàn)在有影印版,直接讀英文比讀中文來得容易。
《Unix網(wǎng)絡(luò)編程卷二》Unix網(wǎng)絡(luò)編程卷第二卷沒有涉及網(wǎng)絡(luò)的東西,主要講進(jìn)程間通訊和Posix線程。



網(wǎng)絡(luò)編程類
《Unix網(wǎng)絡(luò)編程》第一卷講BSD Socket網(wǎng)絡(luò)編程接口和另外一種網(wǎng)絡(luò)編程接口的,不過現(xiàn)在一般都用BSD Socket,所以這本書只要看大約一半多就可以了。
《TCP/IP詳解》一共三卷,卷一講協(xié)議,卷二講實現(xiàn),卷三講編程應(yīng)用,也很經(jīng)典的。
《用TCP/IP進(jìn)行網(wǎng)際互連》一共三卷,內(nèi)容講解十分精彩。卷一講原理,卷二講實現(xiàn),卷三講高級協(xié)議。感覺上這一套要比Stevens的那一套要好,就連Stevens也不得不承認(rèn)它的第一卷非常經(jīng)典。事實上,第一卷即使你沒有一點網(wǎng)絡(luò)的知識,看完以后也會對網(wǎng)絡(luò)的來龍去脈了如指掌。第一卷中還有很多習(xí)題也設(shè)計得經(jīng)典和實用,因為作者本身就是一位教師,并且卷一是國外研究生的教材。習(xí)題并沒有答案,留給讀者思考,因為問題得答案可以讓你成為一個中級的Hacker,這些問題的答案可以象Douglus索取,不過只有他只給教師卷二我沒有怎么看,卷三可以作為參考手冊,其中地例子也很經(jīng)典。
Linux 多線程服務(wù)端編程:使用 muduo C++ 網(wǎng)絡(luò)庫》


Linux系統(tǒng)管理類
《linux系統(tǒng)管理手冊》
《LINUX與UNIX SHELL編程指南》
《Advanced Bash Scripting Guide》


系統(tǒng)內(nèi)核類
《Linux內(nèi)核代碼情景分析》
《深入Linux內(nèi)核源碼》


面向?qū)ο笤O(shè)計類
《設(shè)計模式》
《敏捷軟件開發(fā):原則、模式與實踐》
《敏捷項目管理》


內(nèi)功修煉類
《操作系統(tǒng):設(shè)計與實現(xiàn)(第二版)》
《操作系統(tǒng)概念》
《數(shù)據(jù)結(jié)構(gòu)與算法-面向?qū)ο蟮腃++設(shè)計模式》
《編譯原理》國防陳火旺
《離散數(shù)學(xué)及其應(yīng)用》
《計算機(jī)組織與體系結(jié)構(gòu)?性能分析》
《深入理解計算機(jī)系統(tǒng)》【美】Randal E. Bryant David O'Hallaron著v

posted @ 2014-07-25 20:29 鑫龍 閱讀(1681) | 評論 (0)編輯 收藏

2014年4月8日

程序如下:

import java.util.*;

import java.io.*;

public class BadExecJavac

{

    public static void main(String args[])

    {

        try

        {           

            Runtime rt = Runtime.getRuntime();

            Process proc = rt.exec("javac");

            int exitVal = proc.exitValue();

            System.out.println("Process exitValue: " + exitVal);

        } catch (Throwable t)

          {

            t.printStackTrace();

          }

    }

}

運(yùn)行結(jié)果如下

E:\classes\com\javaworld\jpitfalls\article2>java BadExecJavac
java.lang.IllegalThreadStateException: process has not exited       
at java.lang.Win32Process.exitValue(Native Method)       
at BadExecJavac.main(BadExecJavac.java:13)

這是因為當(dāng)進(jìn)程還沒有結(jié)束的情況下,調(diào)用exitValue方法會拋出IllegalThreadStateException.當(dāng)然了我們會問為什嗎這個方法不會等到進(jìn)程結(jié)束在返回一個合理的值?

在檢查Process類的所有可用方法以后我們發(fā)現(xiàn)WairFor()是一個更合適的方法。事實上waitFor也會返回exit value。這意味著你不可以同時用exitvalue和waitfor,而是只能選擇一個。

當(dāng)然了也有情況你要在waitfor之前用exitvalue方法:就是你不想因為外部程序永遠(yuǎn)無法完成而一直等待下去。

因此為了避免這個陷阱,我們要么捕獲IllegalThreadStateException異常,要么等待進(jìn)程完成。我們相當(dāng)然的以為可以用waitfor來等待程序的結(jié)束。代碼如下:

import java.util.*;
import java.io.*;
public class BadExecJavac2{   
   public static void main(String args[])    {       
      try        {                        
         Runtime rt = Runtime.getRuntime();           
         Process proc = rt.exec("javac");           
         int exitVal = proc.waitFor();           
         System.out.println("Process exitValue: " + exitVal);       
      } catch (Throwable t)          {           
         t.printStackTrace();         
      }   
   }
}

這次在linux下面返回的結(jié)果是2,而在windows下面據(jù)說程序會掛起,關(guān)于其原因我們可以在jdk文檔中找到部分解釋:因為一些操作系統(tǒng)為標(biāo)準(zhǔn)的輸入輸出僅僅提供有限的緩沖區(qū),當(dāng)不能正確的將信息寫進(jìn)輸入流或者從輸出流中獲取信息時,就會導(dǎo)致子進(jìn)程的阻塞,甚至死鎖?,F(xiàn)在我們就根據(jù)jdk文檔來處理javac進(jìn)程的輸出,當(dāng)你不帶任何參數(shù)運(yùn)行javac時,它會打印出一系列的有用的提示信息。而這些會被傳送到stderr流中。我們可以寫程序在其返回前獲取這些信息。下面的代碼提供了一個平庸的解決方案。

import java.util.*;import java.io.*;
public class MediocreExecJavac{   
   public static void main(String args[])    {       
       try        {                        
         Runtime rt = Runtime.getRuntime();           
         Process proc = rt.exec("javac");           
         InputStream stderr = proc.getErrorStream();           
         InputStreamReader isr = new InputStreamReader(stderr);           
         BufferedReader br = new BufferedReader(isr);           
         String line = null;           
         System.out.println("<ERROR>");           
         while ( (line = br.readLine()) != null)               
            System.out.println(line);           
         System.out.println("</ERROR>");           
         int exitVal = proc.waitFor();           
         System.out.println("Process exitValue: " + exitVal);       
      } catch (Throwable t)          {           
          t.printStackTrace();         
      }   
   }
}

這次程序可以正確的輸出了提示信息,但是我們應(yīng)該注意到其返回代碼是2,我們知道任何非0的返回代碼都表示程序不正常。所以我們需要進(jìn)一步的查找原因。對于win32而言是file not found,很明顯javac期望我們提供編譯的文件。所以對于永遠(yuǎn)掛起的問題,如果你運(yùn)行的程序會有輸出或者要求輸出入時,你需要處理輸出和輸入。我在linux下面運(yùn)行的結(jié)果是正確的。前面說了在win32下面2代表是文件沒有找到,而在這種情況下表明是dir.exe沒有找到,(因為根本就沒有這個文件,他們都被封裝到common.com (win95)或者cmd.exe中了。

下面我們列出一個正確的處理Process的輸入輸出流的方法。需要用一個線程類。

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread{   
   InputStream is;   
   String type;        
   StreamGobbler(InputStream is, String type)    {       
       this.is = is;       
       this.type = type;   
   }        

   public void run()    {       
      try        {           
          InputStreamReader isr = new InputStreamReader(is);           
          BufferedReader br = new BufferedReader(isr);           
          String line=null;           
      while ( (line = br.readLine()) != null)               
      System.out.println(type + ">" + line);                
      } catch (IOException ioe)             {               
       ioe.printStackTrace();               
      }   
   }
}

用于專門的處理輸入輸出。

public class GoodWindowsExec{   
    public static void main(String args[])    {       
        if (args.length < 1)        {           
            System.out.println("USAGE: java GoodWindowsExec <cmd>");           
            System.exit(1);       
        }                
        try        {                        
            String osName = System.getProperty("os.name" );           
            String[] cmd = new String[3];           
            if( osName.equals( "Windows NT" ) )            {               
                cmd[0] = "cmd.exe" ;               
                cmd[1] = "/C" ;               
                cmd[2] = args[0];           
            }            else if( osName.equals( "Windows 95" ) )            {               
                cmd[0] = "command.com" ;               
                cmd[1] = "/C" ;               
                cmd[2] = args[0];            }                        
            Runtime rt = Runtime.getRuntime();            
            System.out.println("Execing " + cmd[0] + " " + cmd[1] + " " + cmd[2]);           
            Process proc = rt.exec(cmd);            // any error message?           
            StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");  // any output?           
            StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");                            // kick them off           
            errorGobbler.start();           
            outputGobbler.start();                                                // any error???           
            int exitVal = proc.waitFor();           
            System.out.println("ExitValue: " + exitVal);                
        } catch (Throwable t)          {           
            t.printStackTrace();          
        }   
    }
}

如果運(yùn)行如下命令上面的代碼會調(diào)用word程序

>java GoodWindowExec “abc.doc”

也就是說文件類型如果window能夠識別它就會調(diào)用對應(yīng)的程序處理。

StreamGlobbler的最重要作用是他會清空所有的傳遞給他的inputstream,這樣不會造成Process阻塞或者死鎖。

posted @ 2014-04-08 15:20 鑫龍 閱讀(3471) | 評論 (0)編輯 收藏

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美午夜在线一二页| 欧美亚洲综合在线| 欧美一级夜夜爽| 久久精彩免费视频| 久久婷婷人人澡人人喊人人爽| 先锋资源久久| 久久久水蜜桃av免费网站| 久久婷婷影院| 亚洲国产精品999| 欧美激情视频在线播放| 亚洲青涩在线| 香蕉久久久久久久av网站| 久久久久免费观看| 欧美精品网站| 国产日韩欧美一二三区| **性色生活片久久毛片| 亚洲天堂免费观看| 久久久成人精品| 亚洲日本va午夜在线影院| 亚洲一区二区三区在线| 久久久在线视频| 欧美婷婷久久| 亚洲国产精品久久久久| 亚洲男女自偷自拍| 欧美 日韩 国产 一区| 亚洲美女视频网| 久久久久综合一区二区三区| 欧美日产在线观看| 狠狠色伊人亚洲综合网站色| 亚洲最黄网站| 久久视频精品在线| 99国产成+人+综合+亚洲欧美| 欧美一区二区在线| 欧美日韩一区在线观看视频| 国产综合久久久久久鬼色| 99国产精品99久久久久久| 久久精品视频一| 99在线热播精品免费| 久久婷婷亚洲| 国产日韩精品在线| 亚洲一区在线看| 亚洲国产日韩在线| 久久久久女教师免费一区| 国产精品久久77777| 亚洲精品视频在线播放| 麻豆成人小视频| 欧美一区二区久久久| 国产精品亚洲第一区在线暖暖韩国| 亚洲毛片在线观看| 欧美国产视频在线观看| 久久精品成人| 国内成人精品视频| 久久aⅴ国产欧美74aaa| 在线一区免费观看| 欧美日韩午夜在线| 亚洲最快最全在线视频| 亚洲激情一区二区| 免费久久99精品国产自在现线| 国内精品一区二区三区| 欧美在线免费观看| 性欧美videos另类喷潮| 国产精品午夜春色av| 亚洲在线成人| 亚洲一二区在线| 国产精品稀缺呦系列在线| 欧美亚洲网站| 亚洲欧美日韩国产中文| 国产精品免费小视频| 亚洲综合色丁香婷婷六月图片| 99精品欧美一区| 欧美视频日韩视频| 亚洲欧美日韩国产一区二区| 亚洲视频福利| 国产午夜久久久久| 麻豆av一区二区三区久久| 欧美成人精品三级在线观看| 99re成人精品视频| 一区二区三区四区五区视频 | 久久久久久午夜| 国内外成人免费视频| 久久久亚洲人| 免费观看成人| 亚洲无线一线二线三线区别av| 日韩视频中文| 国产精品自拍网站| 麻豆精品在线视频| 欧美韩日亚洲| 欧美一级大片在线观看| 久久久精品五月天| 日韩一级精品视频在线观看| 夜夜爽av福利精品导航 | 欧美三日本三级少妇三99| 午夜激情亚洲| 免费不卡视频| 亚洲欧美日韩国产一区| 久久久久91| 一区二区国产日产| 小辣椒精品导航| 亚洲人成艺术| 午夜精品福利一区二区蜜股av| 影音先锋亚洲一区| av成人免费| 精品成人在线视频| 在线亚洲免费视频| 亚洲国产精品一区二区三区| 中文亚洲视频在线| 亚洲日本免费| 久久精品视频播放| 亚洲一区黄色| 欧美搞黄网站| 免费观看久久久4p| 国产精品永久免费在线| 欧美二区在线| 国产欧美一区二区三区视频 | 亚洲第一福利在线观看| 国产精品男女猛烈高潮激情| 欧美承认网站| 国产一区视频网站| 一本色道久久综合狠狠躁篇怎么玩| 国产日韩在线亚洲字幕中文| 亚洲欧洲视频在线| 在线看片一区| 亚洲欧美国产三级| 亚洲午夜一二三区视频| 欧美成人a∨高清免费观看| 欧美在线视频全部完| 欧美日韩一区二区三区| 亚洲欧洲在线看| 亚洲黄色免费电影| 久久人91精品久久久久久不卡| 欧美亚洲一级| 国产精品一区二区视频| 亚洲一区二区三区久久 | 欧美亚洲日本网站| 国产精品婷婷| 亚洲国产成人av在线| 亚洲欧美在线aaa| 亚洲尤物在线视频观看| 欧美精品粉嫩高潮一区二区 | 麻豆亚洲精品| 在线精品福利| 另类春色校园亚洲| 欧美成人免费观看| 亚洲激情在线播放| 美女精品一区| 欧美国产一区二区三区激情无套| 激情综合在线| 美女久久一区| 亚洲黑丝在线| 一区二区三区产品免费精品久久75 | 免费影视亚洲| 亚洲国产精品一区制服丝袜| 欧美成人国产va精品日本一级| 欧美国产精品劲爆| 亚洲精品国产系列| 欧美日韩一视频区二区| 亚洲综合另类| 免费成年人欧美视频| 亚洲韩国一区二区三区| 欧美日韩精选| 欧美一区二区精美| 亚洲国产精品成人精品| 亚洲一区二区三区色| 亚洲图片欧美午夜| 久久精品亚洲热| 亚洲国产日韩在线一区模特| 欧美日韩第一区| 西西人体一区二区| 蘑菇福利视频一区播放| 一区二区三区回区在观看免费视频| 国产精品久久二区二区| 久久久久.com| 国产精品99久久久久久久vr| 久久久亚洲成人| 中文av一区二区| 在线精品亚洲| 国产日韩av一区二区| 欧美大片免费观看在线观看网站推荐| 欧美黄色一区二区| 久久爱另类一区二区小说| 亚洲精品欧美精品| 国产免费成人| 欧美日韩成人在线| 久久gogo国模啪啪人体图| 亚洲精品视频在线观看网站| 久久久久国产免费免费| 一区二区欧美视频| 国产一区二区三区在线免费观看| 久久综合色一综合色88| 亚洲免费视频在线观看| 亚洲二区视频| 久久久蜜桃精品| 亚洲一区二区在| 一区二区三区国产精华| 91久久精品美女| 亚洲高清二区| 国外成人在线视频| 欧美日韩精品综合在线| 久久综合色综合88| 久久久免费观看视频|