利用雙緩衝佇列來減少鎖的競爭

2022-07-04 14:06:19 字數 1882 閱讀 1110

在日常的開發中,日誌的記錄是必不可少的。但是我們也清楚對同乙個文字進行寫日誌只能單執行緒的去寫,那麼我們也經常會使用簡單lock鎖來保證只有乙個執行緒來寫入日誌資訊。但是在多執行緒的去寫日誌資訊的時候,由於記錄日誌資訊是需要進行i/o互動的,導致我們占用鎖的時間會加長,從而導致大量執行緒的阻塞與等待。

這種場景下我們就會去思考,我們該怎麼做才能保證當有多個執行緒來寫日誌的時候我們能夠在不利用鎖的情況下讓他們依次排隊去寫呢?這個時候我們就可以考慮下使用雙緩衝佇列來完成。

所謂雙緩衝佇列就是有兩個佇列,乙個是用來專門負責資料的寫入,另乙個是專門負責資料的讀取,當邏輯執行緒讀取完資料後負責將自己的佇列與i/o執行緒的佇列進行交換。

我們該怎麼利用這雙緩衝佇列來完成我們想要的效果呢?

當有多個執行緒來寫日誌的時候,這個時候我們要這些要寫的資訊先放到我們負責寫入的佇列當中,然後將邏輯讀的執行緒設為非阻塞。此時邏輯讀的執行緒就可以開始工作了。(一開始時邏輯讀的佇列是空的)在當邏輯讀的執行緒讀取他自己佇列的資料(並執行一些邏輯)之後,將邏輯讀的佇列的引用和負責寫入的佇列進行引用交換。這就是簡單的乙個雙緩衝佇列實現的乙個思路。具體實現**如下:

public class user 

public string pwd

public override string tostring() ,";}}

public class doublequeue 

public void producerfunc(user user)

public void consumerqueue()

fluentconsole.white.background.red.line($"當前個數,花費了ms;");

system.threading.thread.sleep(20);}}}}}

fluentconsole 是乙個控制台應用程式的輸出外掛程式,開源的,有興趣的可以自己去玩玩。

internal class program ;

doublequeue.producerfunc(user);

});stopwatch watch = stopwatch.startnew();

int allcount = 0;

parallel.for(0, 3000, i =>

;lock (obj)

,花費了ms;");

system.threading.thread.sleep(20);

}});

fluentconsole.black.background.red.line("執行完成");

console.read();}}

第乙個利用雙緩衝佇列來執行,第二個利用lock鎖來執行。下面分別是第一種方法和第二種方法執行時cpu的消耗。

我們可以發現利用雙佇列緩衝的情況下我們減少了cpu的占有。但是我們可能會增加執行的時間。

參考文章:

別人在08年就已經想到了,而我卻在現在才稍微有點想法。

public class doublequeue 

public void producerfunc(user user)

public void consumerqueue()

}fluentconsole.white.background.red.line($"當前個數,花費了ms;");

system.threading.thread.sleep(20);}}}}}

利用雙緩衝佇列來減少鎖的競爭

在日常的開發中,日誌的記錄是必不可少的。但是我們也清楚對同乙個文字進行寫日誌只能單執行緒的去寫,那麼我們也經常會使用簡單lock鎖來保證只有乙個執行緒來寫入日誌資訊。但是在多執行緒的去寫日誌資訊的時候,由於記錄日誌資訊是需要進行i o互動的,導致我們占用鎖的時間會加長,從而導致大量執行緒的阻塞與等待...

利用雙緩衝技術來顯示動畫

什麼是光柵化?什麼是幀?答 一幀就是一副靜止的畫面,連續的幀就形成動畫,如電檢視象等。我們通常說幀數,簡單地說,就是在1秒鐘時間裡傳輸的的幀數,也可以理解為圖形處理器每秒鐘能夠重新整理幾次,通常用fps frames per second 表示。每一幀都是靜止的圖象,快速連續地顯示幀便形成了運動的假...

雙緩衝佇列

前段時間,做了個 雙緩衝佇列 可是測試的效果就是不怎麼明顯,理論完全都在這裡,可是就是看不到效果。昨天在胡總的提示下,終於意識到不該用阻塞佇列,換成普通的list物件,這樣效果就明顯多啦 又重新寫了一篇文件,如下 好,31毫秒。這是我們的第一種解決方法,下面再來看第二種解決方法 其實我們在facto...