前言
在并發(fā)編程中,確保共享資源的同步訪問(wèn)對(duì)防止數(shù)據(jù)損壞和保持?jǐn)?shù)據(jù)一致性至關(guān)重要。互斥鎖(Mutex)是一種用于同步線程訪問(wèn)共享資源的機(jī)制。互斥鎖確保共享資源在同一時(shí)間點(diǎn),只有一個(gè)線程可以訪問(wèn),從而防止資源競(jìng)爭(zhēng)與沖突。本文了解C#中Mutex實(shí)現(xiàn)互斥體的功能。
Mutex
Mutex 是一種同步的原語(yǔ),在實(shí)現(xiàn)線程共享資源同步訪問(wèn),防止數(shù)據(jù)損壞和保持?jǐn)?shù)據(jù)一致性方面起著至關(guān)重要的作用。
1、關(guān)鍵概念
擁有權(quán):在任何給定時(shí)間內(nèi),只有一個(gè)線程可以擁有互斥鎖。擁有互斥鎖的線程,負(fù)責(zé)在使用受保護(hù)資源完成后釋放互斥鎖。
互斥狀態(tài):互斥鎖有二種狀態(tài),分別是處于有信號(hào) (解鎖) 或非有信號(hào) (鎖定) 狀態(tài)。嘗試獲取鎖定互斥鎖的線程將被阻止,直到它可用。
Mutex 的基本操作包括創(chuàng)建、獲取、釋放幾個(gè)基本操作。
在 C# 中,可以使用 System.Threading 命名空間的 Mutex 類創(chuàng)建 Mutex 對(duì)象。
// 創(chuàng)建一個(gè)具默認(rèn)屬性的Mutex 實(shí)例 【未命名且初始所有權(quán)未獲取】
Mutex mutex = new Mutex();
// 創(chuàng)建一個(gè)命名為GlobalMutexName,但初始所有權(quán)未獲取的 Mutex實(shí)例
Mutex mutex = new Mutex(false, "Global_MutexName");
通過(guò)使用類提供的 WaitOne 方法獲取互斥鎖。
// 獲取 Mutex
mutex.WaitOne();
try
{
// 訪問(wèn)共享資源
}
finally
{
mutex.ReleaseMutex();
}
通過(guò)使用類提供的 ReleaseMutex 方法釋放互斥鎖。
// 獲取Mutex
mutex.WaitOne();
try
{
// 訪問(wèn)共享資源
}
finally
{
//釋放
mutex.ReleaseMutex();
}
2.4、為互斥鎖命名
在創(chuàng)建 Mutex 時(shí)可以指定互斥鎖名稱,通過(guò)互斥鎖名稱可以在不同的進(jìn)程之間共享同一個(gè) Mutex 實(shí)例。在跨進(jìn)程同步的應(yīng)用場(chǎng)景中互斥鎖名稱非常有用。
bool createdMutex;
using (Mutex mutex = new Mutex(false, "Global_MutexName", out createdNew))
{
if (!createdMutex)
{
Console.WriteLine("Mutex 已存在,可能已有另一個(gè)實(shí)例在運(yùn)行。");
}
// 請(qǐng)求獲取 Mutex
mutex.WaitOne();
try
{
// 訪問(wèn)共享資源
}
finally
{
// 釋放 Mutex
mutex.ReleaseMutex();
}
}
參考命名
建議使用 Global_ 前綴表示全局、Local_ 前綴表示當(dāng)前,通過(guò)命名前綴以明確 Mutex 的作用范圍。
2.5、使用具有超時(shí)的互斥鎖(Mutex)
我們可以在嘗試獲取互斥鎖時(shí)指定超時(shí),以避免無(wú)限期阻塞。if (mutex.WaitOne(TimeSpan.FromSeconds(8)))
{
try
{
// 訪問(wèn)共享資源
}
finally
{
mutex.ReleaseMutex();
}
}
else
{
// 處理超時(shí)情況
}
3、注意事項(xiàng)
確保 Mutex 對(duì)象釋放:可使用 try...finally 語(yǔ)句塊在訪問(wèn)結(jié)束后確保釋放 Mutex,避免死鎖;
避免長(zhǎng)時(shí)間持有 Mutex:盡量縮短持有 Mutex 的時(shí)間,減少線程等待時(shí)間,提高性能;
做好異常處理:由于在獲取或釋放 Mutex 時(shí)可能會(huì)拋出異常,所以需做好異常處理;
避免互斥鎖名稱重復(fù):互斥鎖名命名時(shí),應(yīng)確保其唯一性,避免與其他應(yīng)用程序的 Mutex 沖突;
示例
1、在多線程應(yīng)用程序中寫(xiě)入文件
namespace Fountain.WinConsole.MutexDemo
{
internal class Program
{
private static Mutex fileMutex = new Mutex();
/// <summary>
/// 程序入口
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
// 啟動(dòng)多個(gè)線程
for (int i = 0; i < 5; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(WriteToFile));
thread.Name = $"線程-{i + 1}";
thread.Start("寫(xiě)入文件的內(nèi)容");
}
Console.ReadKey();
}
/// <summary>
/// 寫(xiě)入文件
/// </summary>
/// <param name="writeContent"></param>
public static void WriteToFile(object writeContent)
{
// 獲取互斥鎖時(shí)指定超時(shí)
if (fileMutex.WaitOne(TimeSpan.FromSeconds(8)))
{
try
{
Console.WriteLine($"{Thread.CurrentThread.Name} 獲得 Mutex。正在訪問(wèn)共享資源...");
Thread.Sleep(400);
Console.WriteLine($"{Thread.CurrentThread.Name} 訪問(wèn)完畢。");
}
finally
{
fileMutex.ReleaseMutex();
Console.WriteLine($"{Thread.CurrentThread.Name} 釋放了 Mutex。");
}
}
else
{
Console.WriteLine($"{Thread.CurrentThread.Name} 處理超時(shí)情況。");
}
}
}
}
小結(jié)
Mutex 可以有效避免同步線程數(shù)據(jù)競(jìng)爭(zhēng)和資源沖突,提高應(yīng)用程序的穩(wěn)定性和可靠性。通過(guò)了解 Mutex,并通過(guò)正確使用Mutex,才能有效地管理并發(fā)訪問(wèn),確保程序的正確性和穩(wěn)定性。希望本文能給您帶來(lái)幫助,如有不到之處,請(qǐng)多多包涵。
該文章在 2024/11/4 10:28:01 編輯過(guò)