永发信息网

C#多线程 如何判断是否处于Lock状态

答案:2  悬赏:60  手机版
解决时间 2021-03-10 23:43
  • 提问者网友:了了无期
  • 2021-03-10 18:43
如果处于Lock,不是系统的默认操作:加入等待队列,而是抛出异常,不等待,如何实现?
最佳答案
  • 五星知识达人网友:渡鹤影
  • 2021-03-10 18:53
Monitor.TryEnter

Monitor底下的这一套实现和lock一样
全部回答
  • 1楼网友:人间朝暮
  • 2021-03-10 19:57

lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。

lock 语句以关键字 lock 开头,它有一个作为参数的对象,在该参数的后面还有一个一次只能由一个线程执行的代码块。例如:

public class testthreading

{

    private system.object lockthis = new system.object();

    public void function()

    {

        lock (lockthis)

        {

            // access thread-sensitive resources.

        }

    }

}

提供给 lock 关键字的参数必须为基于引用类型的对象,该对象用来定义锁的范围。在上例中,锁的范围限定为此函数,因为函数外不存在任何对该对象的引用。如果确实存在此类引用,锁的范围将扩展到该对象。严格地说,提供给 lock 的对象只是用来唯一地标识由多个线程共享的资源,所以它可以是任意类实例。然而,实际上,此对象通常表示需要进行线程同步的资源。例如,如果一个容器对象将被多个线程使用,则可以将该容器传递给 lock,而 lock 后面的同步代码块将访问该容器。只要其他线程在访问该容器前先锁定该容器,则对该对象的访问将是安全同步的。

通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。锁定字符串尤其危险,因为字符串被公共语言运行库 (clr)“暂留”。 这意味着整个程序中任何给定字符串都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。因此,最好锁定不会被暂留的私有或受保护成员。某些类提供专门用于锁定的成员。例如,array 类型提供 syncroot。许多集合类型也提供 syncroot。

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

线程处理(c# 编程指南) 这节讨论了线程处理。

lock 关键字在块的开始处调用 enter,而在块的结尾处调用 exit。

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

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

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

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

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

// 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();

        }

    }

}

详情参见msdn。

我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯