using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Linq;
using System.Data.SqlClient;
using System.Data;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Net.Mail;
using System.Threading;
using System.Collections;
namespace CSharp
{
public class Program
{
static void Main()
{
SS s = new SS();
SS s2 = new SS();
s.Test("s");
Thread.Sleep(100);
s2.Test("s2");
Console.ReadKey();
}
}
public class SS
{
private int i = 0;
//这个地方AL是静态的和非静态区别很大,如果是静态,则 s.Test("s")和 s2.Test("s2") 两个方法是对一个对象加锁,我们在 s.Test("s")后加上Thread.Sleep(100)可以保证s.Test("s")中的两个线程执行完毕以后才会执行 s2.Test("s2") 中的两个线程,若AL不是staitc,因为在s.AL和s2.AL不是同一个对象,所以 s.Test("s")和 s2.Test("s2") 两个方法中锁定的对象不一样,就不能保证s.Test("s")中的两个线程执行完毕以后才会执行 s2.Test("s2") 中的两个线程
static ArrayList AL = new ArrayList(1);
string name;
public void Test(string str)
{
name = str;
AL.Add(0);
Thread t1 = new Thread(Thread1);
Thread t2 = new Thread(Thread2);
t1.Start();
t2.Start();
}
void Thread1()
{
lock (AL)
{
Console.WriteLine(name + ":执行Thread1开始");
Console.WriteLine(name + ":" + AL[0]);
Thread.Sleep(1000);
Console.WriteLine(name + ":" + AL[0]);
Console.WriteLine(name + ":执行Thread1结束");
}
}
void Thread2()
{
lock (AL)
{
Console.WriteLine(name + ":执行Thread2开始");
Thread.Sleep(250);
AL[0]=Convert.ToInt32(AL[0])+1;
Console.WriteLine(name + ":执行Thread2结束");
}
}
}
}
摘抄别人博客的说法:
lock语句根本使用的就是Moniter.Enter和Moniter.Exit,也就是说lock(this)时执行 Moniter.Enter(this),大括号结束时执行Monitor.Exit(this).他的意义在于什么呢,对于任何一个对象来说,他在内存 中的第一部分放置的是所有方法的地址,第二部分放着一个索引,他指向CLR中的SyncBlock Cache区域中的一个SyncBlock.什么意思呢?就是说,当你执行Monitor.Enter(Object)时,如果object的索引值为负 数,就从SyncBlock Cache中选区一个SyncBlock,将其地址放在object的索引中。这样就完成了以object为标志的锁定,其他的线程想再次进行 Monitor.Enter(object)操作,将获得object为正数的索引,然后就等待。直到索引变为负数,即线程使用 Monitor.Exit(object)将索引变为负数。