c# lock,Monitor(介绍) 多线程并发控制

本文介绍了C#中用于多线程并发控制的lock关键字和Monitor类。lock关键字用于创建互斥段,确保同一时刻只有一个线程执行特定代码。Monitor类则提供了线程同步的方法,通过Enter()和Exit()方法锁定和释放对象,防止多个线程同时访问共享资源。在使用Monitor时,通常将Exit()置于try-finally块中以确保锁的正确释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Lock:

c#提供了一个lock关键字,它可以吧一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。

定义如下:

lock(expression) statement_block

expression代表你希望跟踪的对象,通常是对象引用。

& 如果你想保护一个类的实例,一般地,可以使用this;

& 如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了

 而statement_block就是互斥段的代码,这段代码在一个是课内只可能被一个线程执行。

示例如下:

using System;
using System.Threading;

namespace ThreadSimple  
{  
internal class Account   
{  
int balance;  
Random r = new Random();  
 
internal Account(int initial)   
{  
balance = initial;  
}   
internal int Withdraw(int amount)   
{  
if (balance < 0)  
{  
//如果balance小于0则抛出异常  
throw new Exception("Negative Balance");  
}  
//下面的代码保证在当前线程修改balance的值完成之前  
//不会有其他线程也执行这段代码来修改balance的值  
//因此,balance的值是不可能小于0 的  
lock (this)  
{  
Console.WriteLine("Current Thread:"+Thread.CurrentThread.Name);  
//如果没有lock关键字的保护,那么可能在执行完if的条件判断之后  
//另外一个线程却执行了balancebalance=balance-amount修改了balance的值  
//而这个修改对这个线程是不可见的,所以可能导致这时if的条件已经不成立了  
//但是,这个线程却继续执行balancebalance=balance-amount,所以导致balance可能小于0  
if (balance >= amount)   
{  
Thread.Sleep(5);  
balancebalance = balance - amount;  
return amount;  
}   
else   
{  
return 0; // transaction rejected  
}  
}  
}  
internal void DoTransactions()   
{  
for (int i = 0; i < 100; i++)   
Withdraw(r.Next(-50, 100));  
}  
}   
internal class Test   
{  
static internal Thread[] threads = new Thread[10];  
public static void Main()   
{  
Account acc = new Account (0);  
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].Name=i.ToString();  
for (int i = 0; i < 10; i++)   
threads[i].Start();  
Console.ReadLine();  
}  
}  
} 

Monitor类锁定一个对象

当多线程公用一个对象时,也会出现和公用代码类似的问题,这种问题就不应该使用c# lock关键字,这里需要用到Threading中的一个类 Minotor,称之为监视器,Minotor提供了使线程共享资源的方案。

Minotor类可以锁定一个对象,一个线程只有得到这把锁才可以对该对象进行操作。对象锁机制保证了再可能引起混乱的情况下一个时刻只有一个线程可以访问这个对象。Minotor必须和一个具体的对象相关联,但是由于他本身是一个静态类,所以不能使用他来定义对象,而却它的方法都是静态的,不能使用对象来引用。

如下:

       

......  
 
Queue oQueue=new Queue();  
 
......  
 
Monitor.Enter(oQueue);  
 
......//现在oQueue对象只能被当前线程操纵了  
 
Monitor.Exit(oQueue);//释放锁  

如上,当一个线程调用Minotor.Enter()方法锁定一个对象时,这个对象就归它所有了,其他线程想要访问这个对象,只有等待它使用Minoter.Exit()方法释放锁。

一般为了保证线程最终都能释放锁,将Minotor.Exit()方法卸载try-catch-finally结构中的finally代码块中。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值