什么是临界区?
在任意时刻只允许一个线程对共享资源进行访问的区域,也就是多个线程同时访问同一个全局变量,如果都是读取操作,则不会出现问题。 如果一个线程负责改变此变量的值,而其他线程负责同时读取变量内容,则不能保证读取到的数据是经过写线程修改后的。为了确保读线程读取到的是经过修改的变量,就必须在向变量写入数据时禁止其他线程对其的任何访问,直至赋值过程结束后再解除对其他线程的访问限制。
代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
class Lock
{
static readonly object lockObj = new object();
int m = 1;
public void Run()
{
if (m > 0)
{
Console.WriteLine(Thread.CurrentThread.Name + "已进入准备睡眠m值:" + m.ToString());
Thread.Sleep(100);
Console.WriteLine(Thread.CurrentThread.Name + "减之前m值:" + m.ToString());
m = m - 1;
Console.WriteLine(Thread.CurrentThread.Name + "减之后m值" + m.ToString());
if (m < 0)
{
Console.WriteLine("为负数!");
}
Console.WriteLine("-----------------");
}
}
}
class Test
{
private static Thread[] trray = new Thread[10];
public static void Main()
{
Lock l = new Lock();
for (int i = 0; i < 10; i++)
{
trray[i] = new Thread(new ThreadStart(l.Run));
}
for (int i = 0; i < 10; i++)
{
trray[i].Start();
trray[i].Name = "线程:" + i.ToString(); ;
}
Console.ReadLine();
}
}
运行结果
上面的Run方法按逻辑,辅助线程不可能进入代码块if (m < 0)负数里,但看上图的运行结果,已经进入了.我是为什么呢?
是这样的,首先全局变量m初始值为1,10个线程在运行if (m > 0)时都为True,所以都进入了代码块.Thread.Sleep(100);这名意思是等待10个线程都进入.某一线程执行m=m-1,运行后m值为0.这时注意因m为全局变量,所以这时第二个线程的m值为0,而不是初始值1.减之后就为-1了.
如果想要下图正常的结果,加锁.

public void Run()
{
lock (lockObj)
{
Console.WriteLine(Thread.CurrentThread.Name + "已进入lock里");
if (m > 0)
{
//代码如上......
}
}
}
如果变量m为局部变量,如下代码
public void Run()
{
int m =1;
if (m > 0)
{
//代码如上......
}
}
不存在多线程临界区,线程是安全的.运行结果如下:

浙公网安备 33010602011771号