1. 程式人生 > >lock Mutex Monitor 之間的區別與詳解, .net 多執行緒 同步非同步操作,鎖

lock Mutex Monitor 之間的區別與詳解, .net 多執行緒 同步非同步操作,鎖

Framework為我們提供了三個加鎖的機制,分別是Monitor類、Lock關 鍵字和Mutex類。   總體而言,lock和monitor可以鎖定物件,也可以鎖定函式;而mutex一般用於鎖定函式,並保證不同執行緒間同步呼叫函式,而不會受執行緒優先順序影響。使用lock和monitor物件鎖定物件時(即在物件外部鎖定,或者在物件中的函式被呼叫的地方鎖定物件),可以保證該物件一次只被一個執行緒所訪問,但前提是:多個執行緒所鎖定的物件必須是同一個物件,因此這種情況下應該定義一個全域性的物件;鎖定函式時,即在物件中的函式內部加鎖,也可以保證該函式一次只被一個執行緒所訪問,但前提也是各個執行緒訪問的是同一個物件的該函式。而無論lock和monitor事鎖定物件還是函式,都無法保證函式在不同執行緒間的同步,即函式不會被不同執行緒依次訪問,而是優先順序高的執行緒會一直霸佔該物件或物件中的該函式,霸佔一會兒,才會讓給其他執行緒“霸佔”;只有將lock和mutex一起使用,才能讓函式的優先順序失效,保證方法的同步。mutex物件一般在函式內部加鎖,而不是在呼叫函式的地方。
  綜上所述,這三把鎖的異同點如下:   (1)monitor一般在函式呼叫方加鎖;mutex一般在函式內部加鎖,即鎖定被呼叫端;而lock則介於兩者之間,呼叫方和被呼叫方通吃;   (2)使用monitor和lock給呼叫方加鎖時,必須確保不同執行緒所訪問的物件是同一物件,否則根本等於沒鎖;   (3)monitor和lock可以確保一次只有一個執行緒訪問被鎖定部分,但不保證同步;而mutex能夠保證被鎖定物件能夠被不同執行緒同步訪問。

  在多執行緒中,為了使資料保持一致性必須要對資料或是訪問資料的函式加鎖,在資料庫中這是很常見的,但是在程式中由於大部分都是單執行緒的程式,所以沒有加鎖的必要,但是在多執行緒中,為了保持資料的同步,一定要加鎖,好在Framework中已經為我們提供了三個加鎖的機制,分別是Monitor類、Lock關鍵字和Mutex類。

        其中Lock關鍵詞用法比較簡單,Monitor類和Lock的用法差不多。這兩個都是鎖定資料或是鎖定被呼叫的函式。而Mutex則多用於鎖定多執行緒間的同步呼叫。簡單的說,Monitor和Lock多用於鎖定被呼叫端,而Mutex則多用鎖定呼叫端。 例如下面程式:由於這種程式都是毫秒級的,所以執行下面的程式可能在不同的機器上有不同的結果,在同一臺機器上不同時刻執行也有不同的結果,我的測試環境為vs2005, windowsXp , CPU3.0 , 1 G monery。         程式中有兩個執行緒thread1、thread2和一個TestFunc函式,TestFunc會打印出呼叫它的執行緒名和呼叫的時間(mm級的),兩個執行緒分別以30mm和100mm來呼叫TestFunc這個函式。TestFunc執行的時間為50mm。程式如下: using
 System; using System.Collections.Generic; using System.Text; using System.Threading; namespace MonitorLockMutex {     class Program     {         #region variable         Thread thread1 = null;         Thread thread2 = null;         Mutex mutex = null;         #endregion         static void Main(string[] args)         {             Program p = new Program();             p.RunThread();             Console.ReadLine();         }         public Program()         {             mutex = new Mutex();             thread1 = new Thread(new ThreadStart(thread1Func));             thread2 = new Thread(new ThreadStart(thread2Func));         }         public void RunThread()         {             thread1.Start();             thread2.Start();         }         private void thread1Func()         {             for (int count = 0; count < 10; count++)             {                 TestFunc("Thread1 have run " + count.ToString() + " times");                 Thread.Sleep(30);             }         }         private void thread2Func()         {             for (int count = 0; count < 10; count++)             {                 TestFunc("Thread2 have run " + count.ToString() + " times");                 Thread.Sleep(100);             }         }         private void TestFunc(string str)         {             Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString());             Thread.Sleep(50);         }     } } 執行結果如下:         可以看出如果不加鎖的話,這兩個執行緒基本上是按照各自的時間間隔+TestFunc的執行時間(50mm)對TestFunc函式進行讀取。因為執行緒在開始時需要分配記憶體,所以第0次的呼叫不準確,從第1~9次的呼叫可以看出,thread1的執行間隔約是80mm,thread2的執行間隔約是150mm。 現在將TestFunc修改如下: private void TestFunc(string str) {    lock (this)    {       Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString());       Thread.Sleep(50);    } } 或者是用Monitor也是一樣的,如下: private void TestFunc(string str) {       Monitor.Enter(this);       Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString());       Thread.Sleep(50);       Monitor.Exit(this); } 其中Enter和Exit都是Monitor中的靜態方法。 執行Lock結果如下:         讓我們分析一下結果,同樣從第1次開始。相同執行緒間的呼叫時間間隔為執行緒執行時間+TestFunc呼叫時間,不同執行緒間的呼叫時間間隔為TestFunc呼叫時間。例如:連續兩次呼叫thread1之間的時間間隔約為30+50=80;連續兩次呼叫thread2之間的時間間隔約為100+50=150mm。呼叫thread1和thread2之間的時間間隔為50mm。因為TestFunc被lock住了,所以一個thread呼叫TestFunc後,當其它的執行緒也同時呼叫TestFunc時,後來的執行緒即進被排到等待佇列中等待,直到擁有訪問權的執行緒釋放這個資源為止。         這就是鎖定被呼叫函式的特性,即只能保證每次被一個執行緒呼叫,執行緒優先順序高的呼叫的次數就多,低的就少,這就是所謂的強佔式。         下面讓我們看看Mutex類的使用方法,以及與Monitor和Lock的區別。 將程式碼修改如下:         private void thread1Func()         {             for (int count = 0; count < 10; count++)             {                 mutex.WaitOne();                 TestFunc("Thread1 have run " + count.ToString() + " times");                 mutex.ReleaseMutex();             }         }         private void thread2Func()         {             for (int count = 0; count < 10; count++)             {                 mutex.WaitOne();                 TestFunc("Thread2 have run " + count.ToString() + " times");                 mutex.ReleaseMutex();             }         }         private void TestFunc(string str)         {             Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString());             Thread.Sleep(50);         } 執行結果如下:         可以看出,Mutex只能互斥執行緒間的呼叫,但是不能互斥本執行緒的重複呼叫,即thread1中waitOne()只對thread2中的waitOne()起到互斥的作用,但是thread1並不受本wainOne()的影響,可以呼叫多次,只是在呼叫結束後呼叫相同次數的ReleaseMutex()就可以了。         那麼如何使執行緒按照呼叫順序來依次執行呢?其實把lock和Mutex結合起來使用就可以了,改程式碼如下:         private void thread1Func()         {             for (int count = 0; count < 10; count++)             {                 lock (this)                 {                     mutex.WaitOne();                     TestFunc("Thread1 have run " + count.ToString() + " times");                     mutex.ReleaseMutex();                 }             }         }         private void thread2Func()         {             for (int count = 0; count < 10; count++)             {                 lock (this)                 {                     mutex.WaitOne();                     TestFunc("Thread2 have run " + count.ToString() + " times");                     mutex.ReleaseMutex();                 }             }         }

相關推薦

lock Mutex Monitor 之間區別, .net 執行 同步非同步操作,

Framework為我們提供了三個加鎖的機制,分別是Monitor類、Lock關 鍵字和Mutex類。   總體而言,lock和monitor可以鎖定物件,也可以鎖定函式;而mutex一般用於鎖定函式,並保證不同執行緒間同步呼叫函式,而不會受執行緒優先順序影響。使用lo

Java 高併發程式設計執行架構設計

內容簡介 本書主要包含四個部分: 部分主要闡述 Thread 的基礎知識,詳細介紹執行緒的 API 使用、執行緒安全、執行緒間資料通訊,以及如何保護共享資源等內容,它是深入學習多執行緒內容的基礎。 第二部分引入了 ClassLoader,這是因為 ClassLoader 與執行緒不無關係

Java資深架構師大廠執行面試題,細談併發程式設計深造歷程

  多執行緒、執行緒池 多執行緒是實現併發機制的一種有效手段。程序和執行緒一樣,都是實現併發的一個基本單位。執行緒是比程序更小的執行單位,執行緒是程序的基礎之上進行進一步的劃分。所謂多執行緒是指一個程序在執行過程中可以產生多個更小的程式單元,這些更小的單元稱為執行緒,這

muduo網路庫——muduo執行模型

6.3     非阻塞網路程式設計應該用邊沿觸發(ET)還是電平觸發(LT)?如果是電平觸發,那麼什麼時候關注POLLOUT事件?會不會造成busy-loop?如果是邊沿觸發,如果和防止漏讀造成的飢餓? epoll一定比poll快麼? 6.4        在fi

NET執行同步方法(五):訊號量(Semaphore)

   訊號量就像一個夜總會:它有確切的容量,並被保鏢控制。一旦滿員,就沒有人能再進入,其他人必須在外面排隊。那麼在裡面離開一個人後,隊頭的人就可以進入。訊號量的建構函式需要提供至少兩個引數-現有的人數和最大的人數。 訊號

Android SQLite使用執行併發訪問

Android中資料持久化技術包括檔案儲存、SharedPreferences以及資料庫儲存,對於大量複雜的關係型資料,資料庫無疑是最合適的選擇。SQLite是一個輕量級的關係型資料庫,運算速度快,佔用資源少,適合在移動裝置上使用。SQLite不僅支援SQL語法,還遵循資料庫

(七) Java執行之常用執行同步工具類

執行緒同步工具類 訊號燈(Semaphore) 可以維護當前訪問自身的執行緒個數並提供了同步機制,使用Semaphore可以控制同時訪問資源的執行緒個數,示例程式碼如下: public class ThreadExample16 { publi

Java執行之記憶體可見性

可見性:一個執行緒對共享變數值的修改,能夠及時的被其他執行緒看到。  共享變數:如果一個電量在多個執行緒的工作記憶體中都存在副本,那麼這個變數就是這幾個執行緒的共享變數。 JAVA記憶體模型(Java Memory Model)描述了Java程式中各種變數(執行緒共享變

Java執行之synchronized

synchronized是Java中解決併發問題的一種最常用的方法,也是最簡單的一種方法。 synchronized的四種使用方式 修飾程式碼塊:被修飾的程式碼塊稱為同步語句塊,其作用的範圍是大括號{}括起來的程式碼,作用於呼叫物件 修飾方法:被修飾的方法稱為同步方法,其作用的範圍是整個方法,作用於呼叫物件

面向物件-執行(同步函式的是this靜態同步函式的是class)

同步函式使用的是哪一個鎖呢?函式需要被物件呼叫,那麼函式都有一個所屬物件引用,就是this。。所以同步函式使用的鎖是this。程式碼:class Demo implements Runnable { private int t=200; Object obj = new

裝箱和拆箱的區別

深入剖析Java中的裝箱和拆箱   自動裝箱和拆箱問題是Java中一個老生常談的問題了,今天我們就來一些看一下裝箱和拆箱中的若干問題。本文先講述裝箱和拆箱最基本的東西,再來看一下面試筆試中經常遇到的與裝箱、拆箱相關的問題。   以下是本文的目錄大綱:

ArrayList LinkedList的資料結構區別

ArrayLIst 與LinkedList 的區別 1.首先ArrayList 是查詢快,增刪慢; 2.LinkedList 是查詢慢,增刪快; 至於原因下文中已經說明,他們兩個都是執行緒不安全的。 ArrayList的說明 增刪慢 從ArrayList開始說起,首先Arra

Javascript中call和apply的區別

轉自:http://www.7old.com/jiaocheng/show-1412.html在js中call和apply它們的作用都是將函式繫結到另外一個物件上去執行,兩者僅在定義引數方式有所區別,下面我來給大家介紹一下call和apply用法。 在web前端開發過程中

[C#學習筆記之執行2]執行同步併發訪問共享資源工具—LockMonitorMutex、Semaphore

“執行緒同步”的含義         當一個程序啟動了多個執行緒時,如果需要控制這些執行緒的推進順序(比如A執行緒必須等待B和C執行緒執行完畢之後才能繼續執行),則稱這些執行緒需要進行“執行緒同步(thread synchronization)”。         執行緒

Linux 萬用字元 正則表示式 的區別

背景:在linux使用過程中,經常需要查詢檔案,對命令中的萬用字元 pattern 和正則表示式的區分不是很清楚。有必要好好研究一下。 1 掃盲 1.1 萬用字元和正則表示式 當在使用命令列時,有很多時間都用來查詢你所需要的檔案,如 ls find 等。 Sh

pthread_create函式(向執行函式傳遞引數)

一、pthread_create函式: 1、簡介:pthread_create是UNIX環境建立執行緒的函式 2、標頭檔案:#include <pthread.h> 3、函式宣告: int pthread_create(pthread_t* restric

死磕Netty原始碼之記憶體分配(三)PoolThreadCache執行快取記憶體分配

記憶體分配 執行緒私有分配 在介紹PoolArena記憶體分配結構分析的時候提到記憶體分配會先從執行緒快取裡分配,這個執行緒快取其實就是PoolThreadCache PoolThreadCache 成員變數 final PoolA

Java執行同步非同步

1. 多執行緒併發時,多個執行緒同時請求同一資源,必然導致此資源的資料不安全。 2. 執行緒池 在WEB服務中,對於web伺服器的響應速度必須儘可能的快,這就容不得在使用者提交請求按鈕後,再建立執行緒提供服務。為了減少使用者的等待時間,執行緒必須預先建立,放線上程池中,執行

【Boost】boost庫中thread執行5——談談執行中斷

執行緒不是在任意時刻都可以被中斷的。如果將執行緒中函式中的sleep()睡眠等待去掉,那麼即使在主執行緒中呼叫interrupt()執行緒也不會被中斷。 thread庫預定義了若干個執行緒的中斷點,只有當執行緒執行到中斷點的時候才能被中斷,一個執行緒可以擁有任意多箇中斷點。

執行同步中sleepwait區別

1、函式 wait是Object的一個函式,指執行緒處於進入等待狀態,此時執行緒不佔用任何資源,不增加時間限制。wait可以被notify和notifyAll函式喚醒(這兩個也是Object的函