目录
3.Mutex(Boolean, String, Boolean)
一. 特点:
1.非静态类继承
Object->MarshalByRefObject->WaitHandle->Mutex (有兴趣的可以往基类深扒一下)
2.可以跨进程
互斥实现线程同步的原理:
只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。
当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。
互斥量比临界区复杂,因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
二.构造函数
创建一个类供下边调用
public class LudwigMutex {
List<string> names;
public LudwigMutex() {
names = new List<string>();
}
public void Add(string name) {
names.Add(name);
}
public void Sub() {
if(names.Count > 0)
names.RemoveAt(0);
}
public string GetString() {
string str = "";
for(int i = 0; i < names.Count; i++) {
str += names[i] + " - ";
}
return str;
}
}
1.Mutex()
static string[] names = new string[] { "小明", "小话", "小雅", "小斌", "小头"};
static void Main(string[] args) {
Mutex mutex = new Mutex();
LudwigMutex ludwigMutex = new LudwigMutex();
Thread thread = new Thread(() => {
mutex.WaitOne();
for(int i = 0; i < names.Length; i++) {
ludwigMutex.Add(names[i]);
Console.WriteLine(ludwigMutex.GetString());
}
mutex.ReleaseMutex();
});
Thread thread1 = new Thread(() => {
mutex.WaitOne();
for(int i = 0; i < names.Length; i++) {
ludwigMutex.Sub();
Console.WriteLine(ludwigMutex.GetString());
}
mutex.ReleaseMutex();
});
thread.Start();
Thread.Sleep(1000);
thread1.Start();
Console.Read();
}
打印:
1s之后
2.Mutex(Boolean)
参数1:指示调用线程是否应具有互斥体的初始所有权
注:如果在主线程传入true,那么别的线程是获取不到锁的,除非本该线程调用ReleaseMutex()。
因此线程创建传入true时 如果不调用mutex.ReleaseMutex() 其他线程就一直拿不到互斥对象一直没法执行
例1.不调用mutex.ReleaseMutex()
static string[] names = new string[] { "小明", "小话", "小雅", "小斌", "小头"};
static void Main(string[] args) {
Mutex mutex = new Mutex(true);
LudwigMutex ludwigMutex = new LudwigMutex();
Thread thread = new Thread(() => {
mutex.WaitOne();
for(int i = 0; i < names.Length; i++) {
ludwigMutex.Add(names[i]);
Console.WriteLine(ludwigMutex.GetString());
}
mutex.ReleaseMutex();
});
Thread thread1 = new Thread(() => {
mutex.WaitOne();
for(int i = 0; i < names.Length; i++) {
ludwigMutex.Sub();
Console.WriteLine(ludwigMutex.GetString());
}
mutex.ReleaseMutex();
});
thread.Start();
Thread.Sleep(1000);
thread1.Start();
Thread.Sleep(1000);
//mutex.ReleaseMutex();
Console.Read();
}
打印:
例2.调用mutex.ReleaseMutex()
static string[] names = new string[] { "小明", "小话", "小雅", "小斌", "小头"};
static void Main(string[] args) {
Mutex mutex = new Mutex(true);
LudwigMutex ludwigMutex = new LudwigMutex();
Thread thread = new Thread(() => {
mutex.WaitOne();
for(int i = 0; i < names.Length; i++) {
ludwigMutex.Add(names[i]);
Console.WriteLine(ludwigMutex.GetString());
}
mutex.ReleaseMutex();
});
Thread thread1 = new Thread(() => {
mutex.WaitOne();
for(int i = 0; i < names.Length; i++) {
ludwigMutex.Sub();
Console.WriteLine(ludwigMutex.GetString());
}
mutex.ReleaseMutex();//如果没有这一句
});
thread.Start();
Thread.Sleep(1000);
thread1.Start();
Thread.Sleep(1000);
mutex.ReleaseMutex();
Console.Read();
}
打印:
2. Mutex(Boolean, String)
参数1:指示调用线程是否应具有互斥体的初始所有权
参数2:字符串是否为互斥体的名称
Mutex mutex = new Mutex(false, "LudwigMutex");
此时可以跨进程使用
例:
窗体应用:
public partial class Form1 : Form {
Thread thread;
Mutex mutex;
bool write;
public Form1() {
InitializeComponent(); Init();
}
private void Init() {
if(!Mutex.TryOpenExisting("LudwigMutex", out mutex))
mutex = new Mutex(false, "LudwigMutex");
thread = new Thread(() => {
mutex.WaitOne();
using(FileStream fs = File.Open("G:/111/123.txt", FileMode.OpenOrCreate)) {
using(StreamWriter sw = new StreamWriter(fs)) {
while(write) {
sw.WriteLine("程序2写入");
Thread.Sleep(100);
}
sw.Close();
}
fs.Close();
}
mutex.ReleaseMutex();
});
}
private void button1_Click(object sender, EventArgs e) {
write = false;
}
private void button2_Click(object sender, EventArgs e) {
thread.Start();
write = true;
}
}
控制台应用:
class Program {
static string[] names = new string[] { "小明", "小话", "小雅", "小斌", "小头"};
static void Main(string[] args) {
Mutex mutex;
if(!Mutex.TryOpenExisting("LudwigMutex", out mutex))
mutex = new Mutex(false, "LudwigMutex");
LudwigMutex ludwigMutex = new LudwigMutex();
Console.WriteLine("进入程序1");
Thread thread = new Thread(() => {
mutex.WaitOne();
using(FileStream fs = File.Open("G:/111/123.txt", FileMode.OpenOrCreate)) {
using(StreamWriter sw = new StreamWriter(fs)) {
for(int i = 0; i < names.Length; i++) {
ludwigMutex.Add(names[i]);
Console.WriteLine(ludwigMutex.GetString());
sw.WriteLine(names[i]);
}
}
}
mutex.ReleaseMutex();
});
thread.Start();
Thread.Sleep(1000);
Console.Read();
}
}
效果:
1.先启动窗体应用:
点击button2(开始锁定)
2.启动控制台应用
3.点击窗体应用的button1(解除互斥锁)
此时控制台应用打印
4.123.txt的内容为
3.Mutex(Boolean, String, Boolean)
参数1:指示调用线程是否应具有互斥体的初始所有权
参数2:字符串是否为互斥体的名称
参数3:为了知道自己构造出来的互斥锁是不是已经存在,如果锁存在,那么createdNew的变为false,否则为true
代码如下:
1.
class Program {
static string[] names = new string[] { "小明", "小话", "小雅", "小斌", "小头"};
static void Main(string[] args) {
Mutex mutex = new Mutex(false, "LudwigMutex");
bool have = false;
Mutex mutex1 = new Mutex(false, "LudwigMutex", out have);
Console.WriteLine(have);
}
}
打印:
2.
class Program {
static string[] names = new string[] { "小明", "小话", "小雅", "小斌", "小头"};
static void Main(string[] args) {
Mutex mutex = new Mutex(false, "LudwigMutex");
bool have = false;
Mutex mutex1 = new Mutex(false, "LudwigMutex1", out have);
Console.WriteLine(have);
}
}
打印:
三.方法
OpenExisting(String)
打开指定的已命名的互斥体(如果已经存在)。
ReleaseMutex()
释放 Mutex 一次。
TryOpenExisting(String, Mutex)
打开指定的已命名的互斥体(如果已经存在),并返回指示操作是否成功的值。
这几个方法上面例子中已有使用不再赘述