lock:lock语句时设置锁定和解除锁定的一种简单方式。
lock关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
一、通常怎么使用?
1、通常是,我们将lock的对象设置为,私有的,只读并且是引用类型的。也是最佳的实践
private readonly static object oLock = new object(); //只读的静态锁,静态变量所有的用户共享一个 这个可以实现共享锁的安全
私有,是防止外部访问到锁。简言之,谁锁定,谁打开是最安全的。
只读是初始时锁已经创建了,不能再使用过程中更改。
引用类型而不是值类型,1、因为编译过程中,锁定值类型会报错;2、而且值类型,锁定的是副本。但是引用类型中,字符串是个例外,不能当做锁对象
2、还可以是下面的这样
private readonly object oLock = new object();
将锁设定为只读的,实例锁。但是这种锁使用有局限,就是每创建一个实例对象,就会创建一个锁,不是线程安全的。
上面的两种锁,需要视情况而定,如果是多个实例的情况下需要线程安全,则使用私有只读静态锁,所有实例对象共享一个锁。
其实我们判断是否线程安全,简单的方式是,锁定资源的锁,是一个锁还是多个锁,多个任务访问一块资源,则需要一个锁。
下面分享一个例子,上面的两种锁都可以使用,因为只生成一个锁。
internal class Program
{
static internal Thread[] threads = new Thread[5];
private static Random r = new Random();
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
Acount acou = new Acount(10000);
Thread t = new Thread(new ThreadStart(()=> {
acou.WithDar(r.Next(9000, 10000));
}));
threads[i] = t;
threads[i].Name = i.ToString();
threads[i].Start();
}
Console.ReadLine();
}
}
/// <summary>
/// 客户账号
/// </summary>
internal class Acount
{
int acount;
internal Acount(int acount)
{
this.acount = acount;
}
internal int WithDar(int balacn)
{
if (balacn < 0)
{
Console.WriteLine("值小于0");
}
WriteLine($"CurrentThread:{Thread.CurrentThread.Name},等待中,准备取款{balacn}");
if (acount >= balacn)
{
int m = BankAcount._BankAcount.GetMoney(Thread.CurrentThread.Name, balacn);
if (m > 0)
{
WriteLine();
WriteLine("=====================取款信息=======================");
acount = acount - balacn;
WriteLine("CurrentThread:" + Thread.CurrentThread.Name);
WriteLine("取款:" + balacn);
WriteLine("账户余额:" + acount);
WriteLine("====================================================");
WriteLine();
return acount;
}
return 0;
}
else
{
WriteLine($"{Thread.CurrentThread.Name}:个人账户余额不足");
return 0;
}
}
}
/// <summary>
/// 银行账户
/// </summary>
internal class BankAcount
{
private int AllMoney = 40000; //银行账户,每天限额,取这么多
public static BankAcount _BankAcount = null;
private readonly static object oLock = new object(); //增加一个静态锁,用于所有账户公用一个。
//private object oLock = new object(); //实例锁,该类只能有一个实例
static BankAcount()
{
_BankAcount = new BankAcount(); //银行账户
}
/// <summary>
/// 取钱
/// </summary>
/// <param name="zhid">用户ID</param>
/// <param name="qq">取钱</param>
/// <returns></returns>
public int GetMoney(string zhid, int qq)
{
lock (oLock)
{
if (qq <= AllMoney)
{
WriteLine($"{zhid} 取钱 {qq}");
AllMoney -= qq;
WriteLine($"银行记账减去{qq},剩余{AllMoney}");
return qq;
}
else
{
WriteLine($"银行账户余额剩余{AllMoney},取钱{qq}");
WriteLine("银行账户余额不足,请明天来取");
return 0;
}
}
}
}