2011-10-20 36 views
1

我正在從一個類構造幾個對象,並使用這些類中的特定函數來啓動線程。現在,包含構建這些對象的成員函數的Class擁有一個靜態專用Mutex成員。我將這個靜態成員傳遞給構造函數,並且在每個構造函數中,傳遞的Mutex(可能是通過引用)被分配給另一個本地成員。互斥對象是否通過引用傳遞?

如果我然後使用這些本地Mutex成員中的每一個來確保線程安全,我將能夠實現這一目標嗎?我相信這樣一個事實,無論包含Thread函數的對象有多少個不同的實例存在,因爲它們都指向相同的Mutex對象,所以如果使用得當,線程安全性將得到保證。

請從下面的代碼片段代表理念:

Class ThreadClass 
{ 
private Mutex myCopyOfMutex; 
public ThreadClass(Mutex _globalMutex) 
{ 
myCopyOfMutex = _globalMutex; 
} 
public ThreadFunction() 
{ 

// Wait until it is safe to enter. 
myCopyOfMutex.WaitOne(); 
// critical code 

// Release the Mutex. 
myCopyOfMutex.ReleaseMutex(); 

} 
} 

Class MotherClass 
{ 
    private static Mutex mut = new Mutex(); 

    ThreadClass one = new ThreadClass(mut); // first instance 
    Threadclass two = new ThreadClass(mut); // second instance 

// Assign the Thread function to run on separate Thread 

} 

回答

3

是的,它會工作。不,它不是通過引用傳遞的。

有通過一個參考並傳遞通過參考之間的重要區別。

當傳遞引用類型的方法,它通常作爲傳遞一個參考

爲了通過參考傳遞參數,可以使用ref關鍵字:

SomeMethod(ref mutex); 

方法簽名中的參數也必須使用ref關鍵字聲明:

public void SomeMethod(ref Mutex mutex) { 

通過引用傳遞一個可變意味着你傳遞給變量,而不是包含在該變量的基準的一個副本的引用。然後該方法可以更改變量本身,而不僅僅是參考指向的對象。

在大多數情況下,也是在這種情況下,您應該以常規方式傳遞參數。通過引用傳遞只有在您因特定原因需要時纔會執行。

+0

感謝您的回覆和澄清。其實我暗示作爲參考傳遞,但得到的語言混合起來:)。 –

1

(答案完全重寫,老答案是在底部)

通常,System.Threading.Mutex用於進程間通信。如果你只是想在同一個過程中同步你的線程,那麼使用一個完整的Mutex是一個矯枉過正的過程。你可以用任何物體與lock操作:

Class ThreadClass 
{ 
    // static is important, this way the object is shared among all 
    // class instances 
    private static object myMutex = new object(); 

    public ThreadFunction() 
    { 
     // Wait until it is safe to enter. 
     lock(myMutex) 
     { 
      // critical code 
     } 
     // the mutex is automatically released after leaving the block. 
    } 
} 

Class MotherClass 
{ 
    ThreadClass one = new ThreadClass(); // first instance 
    Threadclass two = new ThreadClass(); // second instance 

    // Assign the Thread function to run on separate Thread 
} 

lock -approach的優點是早收益和異常安全(想象一下,如果關鍵代碼拋出一個異常,會發生什麼情況的可能性;但看看埃裏克利珀的article about exceptions under lock )。

如果整個方法是至關重要的,並且有沒有更多類中的關鍵方法,你可以做到這一點更簡單:

Class ThreadClass 
{ 
    [MethodImpl(MethodImplOptions.Synchronized)] 
    public ThreadFunction() 
    { 
     // critical code 
    } 
} 

Class MotherClass 
{ 
    ThreadClass one = new ThreadClass(); // first instance 
    Threadclass two = new ThreadClass(); // second instance 

    // Assign the Thread function to run on separate Thread 
} 

(舊答案就在這裏保留一致性)

所有類實例都通過C#中的引用傳遞。如果您的互斥鎖是一個類(例如,它是System.Threading.Mutex),它將自動通過引用傳遞。

請看here瞭解更多信息。


更正:
作爲@Guffa正確地指出,你不按引用傳遞一個類的實例,但參考一個類實例的值(如果不使用ref關鍵字)。爲了你的目的,實際上它幾乎是一樣的。區別在於傳遞引用中的更改在被調用方之外不可見。

1

是互斥體是通過引用傳遞,因爲它們是類類型不是結構類型

0

從您的簡報中,我假設您正在使用Mutex來同步共享資源訪問。

Mutex是一種託管引用類型,它覆蓋使用Win32中的非託管互斥體。要回答你的問題,是的,它是一個參考類型。

但你的問題使我想到兩點

  1. 爲什麼你擔心的參考?

我的建議是,如果您擔心要共享相同的互斥體實例,請繼續並創建一個命名的互斥體(檢查互斥鎖的構造函數重載)。祕密操作系統將確保這個命名Mutex的同步訪問。

  1. 爲什麼你想要Mutex實例是靜態的?

我的建議是,靜態變量由JIT在與AppDomain關聯的特殊堆中分配。這被稱爲Loader堆。除非您卸載/重新加載AppDomain,否則此加載器堆永遠不會收集垃圾。所以我的觀點是,如果你使用Mutex作爲靜態成員,那麼你可能最終會持有大量的互斥量句柄。

相關問題