• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#多线程MutexMonitorLock

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

lock关键字

 

lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下:

Object thisLock = new Object();
lock (thisLock)
{
    // Critical code section
}

lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

lock 调用块开始位置的 Enter 和块结束位置的 Exit

通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:

  • 如果实例可以被公共访问,将出现 lock (this) 问题。

  • 如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。

  • 由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。

最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。

下例使用线程和 lock。只要 lock 语句存在,语句块就是临界区并且 balance 永远不会是负数。

// statements_lock2.cs
using System;
using System.Threading;

class Account
{
    private Object thisLock = new Object();
    int balance;

    Random r = new Random();

    public Account(int initial)
    {
        balance = initial;
    }

    int Withdraw(int amount)
    {
        // This condition will never be true unless the lock statement
        // is commented out:
        if (balance < 0)
        {
            throw new Exception("Negative Balance");
        }

        // Comment out the next line to see the effect of leaving out 
        // the lock keyword:
        lock(thisLock)
        {
            if (balance >= amount)
            {
                Console.WriteLine("Balance before Withdrawal :  " + balance);
                Console.WriteLine("Amount to Withdraw        : -" + amount);
                balance = balance - amount;
                Console.WriteLine("Balance after Withdrawal  :  " + balance);
                return amount;
            }
            else
            {
                return 0; // transaction rejected
            }
        }
    }

    public void DoTransactions()
    {
        for (int i = 0; i < 100; i++)
        {
            Withdraw(r.Next(1, 100));
        }
    }
}

class Test
{
    static void Main()
    {
        Thread[] threads = new Thread[10];
        Account acc = new Account(1000);
        for (int i = 0; i < 10; i++)
        {
            Thread t = new Thread(new ThreadStart(acc.DoTransactions));
            threads[i] = t;
        }
        for (int i = 0; i < 10; i++)
        {
            threads[i].Start();
        }
    }
}

 

如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

相反,Semaphore 类不强制线程标识。

在 .NET Framework 2.0 版之前,这样不会引发任何异常。

如果出现被放弃的 mutex,通常表明代码中存在严重错误。如果某个线程在未释放互斥体时便退出,受此互斥体保护的数据结构可能处于不一致的状态。如果此数据结构的完整性能得到验证,下一个请求此互斥体所属权的线程就可以处理此异常并继续。因此推荐把Mutex.ReplaceMutex()放在try-catch-finally结构中的finally中。

对于系统范围的 mutex,被放弃的 mutex 可能指示应用程序已突然终止(例如,通过使用 Windows 任务管理器终止)。

Mutex 对象都表示一个单独的局部 mutex。

Mutex 对象来表示同一命名系统 mutex,而且您可以使用 OpenExisting 方法打开现有的命名系统 mutex。

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

 

Monitor 类

Monitor 来确保不会允许其他任何线程访问正在由锁的所有者执行的应用程序代码节,除非另一个线程正在使用其他的锁定对象执行该代码。

Monitor 具有以下功能:

  • 它根据需要与某个对象相关联。

  • 它是未绑定的,也就是说可以直接从任何上下文调用它。

  • Monitor 类的实例。

将为每个同步对象来维护以下信息:

  • 对当前持有锁的线程的引用。

  • 对就绪队列的引用,它包含准备获取锁的线程。

  • 对等待队列的引用,它包含正在等待锁定对象状态变化通知的线程。

  • 下表描述了访问同步对象的线程可以采取的操作:

     

    操作

    说明

    Enter ,TryEnter

    其他任何线程都不能进入临界区,除非它使用其他锁定对象执行临界区中的指令。

    Wait

    脉冲信号用于通知等待线程有关对象状态的更改。

    Pulse (信号),PulseAll

    一旦线程拥有了锁,它就可以检查对象的新状态以查看是否达到所需状态。

    Exit

    此操作还标记受锁定对象保护的临界区的结尾。

    Finally 中)以确保释放监视器。

    如果释放在所有事例中的锁定非常重要,即使在该锁定保护的资源的状态可能不一致时,也请使用这些重载。

    lock 语句而不是该属性。

    Exit 语句可以跨越成员或类的边界或同时跨越两者的边界,但并不推荐这样做。

    锁定外部对象可能导致死锁,这是因为不相关的代码可能会出于不同的目的而选择锁定相同的对象。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#GDI绘制波形图发布时间:2022-07-14
下一篇:
C#代码实现,确保windows程序只有一个实例(instance)发布时间:2022-07-14
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap