当前位置:编程学习 > C#/ASP.NET >>

【求解】关于Net中的Mutex实现线程/进程互斥的问题....

写了段代码,其中有句关于Mutex声明方式,分别采用了带名称的和不带名称的,代码如下:

            //Mutex mutex = new Mutex(false, "MyMutex");//带名称
            Mutex mutex = new Mutex(false);             //不带名称
            mutex.WaitOne();
            try
            {
                string str = ".....";//省略......
                Console.WriteLine(str);
                Thread.Sleep(1000);

            }
            catch (Exception)
            {
            }
            mutex.ReleaseMutex();




带有初始名称的声明方法的运行结果显示如下:


不带初始名称的声明方法的运行结果显示如下:


运行了很多次,都是这种结果,

执行的顺序。

求解释为什么.....


另外看MSDN上的关于Mutex的说明其中有部分觉得不太清楚,如下:


本地 mutex 和系统 mutex
--------------------------------------------------------------------------------
Mutex 分两种类型:本地 mutex 和命名系统 mutex。如果使用接受名称的构造函数创建了 Mutex 对象,那么该对象将与具有该名称的操作系统对象相关联。命名的系统 mutex 在整个操作系统中都可见,并且可用于同步进程活动。您可以创建多个 Mutex 对象来表示同一命名系统 mutex,而且您可以使用 OpenExisting 方法打开现有的命名系统 mutex。
 
本地 mutex 仅存在于进程当中。进程中引用本地 Mutex 对象的任意线程都可以使用本地 mutex。每个 Mutex 对象都是一个单独的本地 mutex。 

是不是这个意思:
 Mutex mutex = new Mutex(false, "MyMutex");  //带名称 这种情况下声明的Mutex就是系统Mutex,在整个操作系统中可见?
 Mutex mutex = new Mutex(false);             //不带名称,本地的仅存在与进程中的,只是统一进程中的线程之间可见??

还有一段:


注意

在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见。如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。在这种情况下,服务器上各个其他终端服务器会话中都可以拥有一个名称相同的独立 mutex。如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”。在终端服务器会话中,只是名称前缀不同的两个 mutex 是独立的 mutex,这两个 mutex 对于终端服务器会话中的所有进程均为可见。即:前缀名称“Global\”和“Local\”说明 mutex 名称相对于终端服务器会话(而并非相对于进程)的范围。
 

不明白什么意思... --------------------编程问答-------------------- 就是那个意思, 不带名称的只有通过他的实例来操作,带了名称的就全局可见
带了名称的又分两种 --------------------编程问答-------------------- 从你的输出看不出来什么……惭愧
第一段就是你说的那个意思,第二段就是说在远程桌面会话连接的情况下mutex作用范围的问题 --------------------编程问答-------------------- 能分别解释下这个作用范围的区别吗?

我不明白
引用 2 楼  的回复:
从你的输出看不出来什么……惭愧
第一段就是你说的那个意思,第二段就是说在远程桌面会话连接的情况下mutex作用范围的问题
--------------------编程问答--------------------

写个例子
两个控制台程序


using System;
using System.Threading;

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main()
        {
            bool bCreateNew = false;
            Mutex mutex = new Mutex(true, "MyMutex", out bCreateNew);
            if (!bCreateNew)
            {
                Console.WriteLine("ConsoleApplication2 已经运行");
            }
            else
            {
                Console.WriteLine("ConsoleApplication2 没有运行");
            }        

            Console.ReadKey();
        }
    }
}



using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication2
{
    class Program
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr OpenMutex(uint dwDesiredAccess, bool bInheritHandle,string lpName);

        [DllImport("kernel32.dll")]
        static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner,string lpName);

        const UInt32 MUTEX_ALL_ACCESS = 0x1F0001;

        static void Main()
        {
            if (OpenMutex(MUTEX_ALL_ACCESS, true, "MyMutex") != IntPtr.Zero)
            {
                Console.WriteLine("ConsoleApplication1 已经运行");
            }
            else
            {
                if (CreateMutex(IntPtr.Zero, true, "MyMutex") == IntPtr.Zero)
                {
                    Console.WriteLine("出错");
                }

                Console.WriteLine("ConsoleApplication1 没有运行");
            }

            Console.ReadKey();
        }
    }
}
--------------------编程问答-------------------- 在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见(就是说在所有远程连接到终端服务器的会话中都可见)。如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。在这种情况下,服务器上各个其他终端服务器会话中都可以拥有一个名称相同的独立 mutex(就是只要以Local\打头了,各个会话中可以存在相同名称的mutex并且只在当前会话可见)。如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”(默认是创建它的会话中可见)。在终端服务器会话中,只是名称前缀不同的两个 mutex 是独立的 mutex,这两个 mutex 对于终端服务器会话中的所有进程均为可见。即:前缀名称“Global\”和“Local\”说明 mutex 名称相对于终端服务器会话(而并非相对于进程)的范围。
--------------------编程问答--------------------
引用 5 楼  的回复:
在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见(就是说在所有远程连接到终端服务器的会话中都可见)。如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。在这种情况下,服务器上各个其他终端服务器会话中都可以拥有一个名称相同的独立 mutex(就是只要以Loc……


请问楼上,在MSDN中有这么一句话“指示调用线程是否应拥有互斥体的初始所属权的布尔值”这句话是什么意思呢?   如果第一个参数为true则标示什么含义呢? --------------------编程问答--------------------
引用 6 楼  的回复:
引用 5 楼  的回复:

在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见(就是说在所有远程连接到终端服务器的会话中都可见)。如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。在这种情况下,服务器上各个其他终端服务器会话中都可以拥有一个名称相同的独……



Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

可以使用 WaitHandle.WaitOne 方法请求互斥体的所属权。拥有互斥体的线程可以在对 WaitOne 的重复调用中请求相同的互斥体而不会阻止其执行。
--------------------编程问答-------------------- 那么我把第一个参数改为true之后,在测试上面的代码,为什么出现了“出现被放弃的。。。”的异常呢?
这该怎么处理?
引用 7 楼  的回复:
引用 6 楼  的回复:

引用 5 楼  的回复:

在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见(就是说在所有远程连接到终端服务器的会话中都可见)。如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。在这种情况下,服务器上各个其他终端服务器……
--------------------编程问答--------------------
引用 8 楼  的回复:
那么我把第一个参数改为true之后,在测试上面的代码,为什么出现了“出现被放弃的。。。”的异常呢?
这该怎么处理?
引用 7 楼  的回复:

引用 6 楼  的回复:

引用 5 楼  的回复:

在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见(就是说在所有远程连接到终……

哪段代码?是不是没有ReleaseMutex线程就终止了? --------------------编程问答--------------------
引用 9 楼  的回复:
引用 8 楼  的回复:

那么我把第一个参数改为true之后,在测试上面的代码,为什么出现了“出现被放弃的。。。”的异常呢?
这该怎么处理?
引用 7 楼  的回复:

引用 6 楼  的回复:

引用 5 楼  的回复:

在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均……


          Mutex mutex = new Mutex(true,"MyMutex");             
            mutex.WaitOne();
            try
            {
                string str = ".....";//省略......
                Console.WriteLine(str);
                Thread.Sleep(1000);

            }
            catch (Exception)
            {
            }
            mutex.ReleaseMutex();



当线程再次执行到“ mutex.WaitOne();”时抛出异常了 --------------------编程问答--------------------  static void Main(string[] args)
        {
            //CFDBLogService.ErrorLog("", "22", "33");
            //CFDBLogService.InfoLog("", "22", "333");
            //CFDBLogService.WarningLog("", "22", "3333");

            for (int i = 0; i < 10; i++)
            {
                (new Thread(new ParameterizedThreadStart(ThreadFunc))).Start(i.ToString());
            }

            Console.ReadKey();
        }
--------------------编程问答-------------------- public Mutex(
bool initiallyOwned,
string name
)


如果 name 不为 null 且 initiallyOwned 为 true,则只有当已命名的系统互斥体是通过此调用创建的时,调用线程才拥有该互斥体。由于没有机制来确定是否创建了已命名的系统互斥体,因此,当调用此构造函数重载时,最好将 initiallyOwned 指定为 false。如果需要确定初始所属权,可以使用 Mutex(Boolean, String, Boolean) 构造函数。


msdn的说明
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,