Try again

200512270453934121.gif

博客园 首页 联系 管理
多个线程可能会试图同时访问某个对象。在多个线程同时争相访问某个对象的同时,如果一个线程修改了资源,有些线程可能会收到无效状态。例如,如果某个线程读取对象的字段,同时另一线程正在修改该字段,则第一个线程可能会收到无效的字段状态。这种情况称为竞用情况。

要避免这种情况,可以通过使用锁定,帮助防止代码的关键部分出现竞用情况。锁定由 Visual C# 关键字 lock 语句表示,允许执行一个线程来获取对某个对象的独占执行权。下列示例步骤演示了锁定:
1. 打开 Visual Studio .NET。
2. 在“文件”菜单上,指向“新建”,然后单击“项目”。
3. 单击“项目类型”下的“Visual C# 项目”,然后单击“模板”下的“控制台应用程序”。
4. 在“名称”文本框中,键入 MultiThreadLockApplication,然后单击“确定”。
5. 将 Class1.cs 中的现有代码替换为以下代码:

using System;
using System.Threading;

namespace MultiThreadLockApplication
{
class Student
{
private static string myTeacherName = "Bill";
private string myName = "Grace";
private static object somePrivateStaticObject = new Object();

public static string TeacherName
{
get
{
string theName;

// Synchronize access to the shared member.
lock(somePrivateStaticObject)
{
Console.WriteLine("Thread {0} starts to get the teacher's name",Thread.CurrentThread.GetHashCode());
theName = myTeacherName;

// Wait for 0.3 second.
Thread.Sleep(300);
Console.WriteLine("Thread {0} finished to get the teacher's name:{1}.", Thread.CurrentThread.GetHashCode(), theName);
}
return theName;
}

set
{
lock(somePrivateStaticObject)
{
Console.WriteLine("Thread {0} starts to set the teacher's name.", Thread.CurrentThread.GetHashCode());
myTeacherName = value;

// Wait for 0.3 second.
Thread.Sleep(300);
Console.WriteLine("Thread {0} finished to set the teacher's name:{1}.", Thread.CurrentThread.GetHashCode(), value);
}
}
}

public string GetName()
{
string theName;
lock(this)
{
Console.WriteLine("Thread {0} starts to get the student's name.", Thread.CurrentThread.GetHashCode());
theName = myName;

// Wait for 0.3 second.
Thread.Sleep(300);
Console.WriteLine("Thread {0} finished to get the student's name:{1}", Thread.CurrentThread.GetHashCode(), theName);
return theName;
}
}

public string SetName(string NewName)
{
string theOldName;
lock(this)
{
Console.WriteLine("Thread {0} starts to set the student's name.", Thread.CurrentThread.GetHashCode());
theOldName = myName;
myName = NewName;

// Wait for 0.3 second.
Thread.Sleep(300);
Console.WriteLine("Thread {0} finished to set the student's name:{1}", Thread.CurrentThread.GetHashCode(), NewName);
}
return theOldName;
}
}

class Class1
{
public static int WorkItemNum = 20;
public static AutoResetEvent Done = new AutoResetEvent(false);

public static void AccessClassResource(object state)
{
Random rnd = new Random();
string theName;
Student AStudent = (Student) state;

if( (rnd.Next() %2) != 0)
{
if( (rnd.Next() %2) != 0)
{
switch (rnd.Next() %3 )
{
case 0:
Student.TeacherName = "Tom";
break;
case 1:
Student.TeacherName = "Mike";
break;
case 2:
Student.TeacherName = "John";
break;
}
}
else
{
theName = Student.TeacherName;
}
}
else
{
if( (rnd.Next() %2) != 0)
{
switch (rnd.Next() %3 )
{
case 0:
AStudent.SetName("Janet");
break;
case 1:
AStudent.SetName("David");
break;
case 2:
AStudent.SetName("Ben");
break;
}
}
else
{
theName = AStudent.GetName();
}
}

if(Interlocked.Decrement( ref WorkItemNum) == 0)
{
Done.Set();
}
}

[STAThread]
static void Main(string[] args)
{
int threadNum;
Student AStudent = new Student();

// Queue up 20 work items in the ThreadPool.
for (threadNum = 0 ; threadNum <= WorkItemNum -1 ; threadNum++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(AccessClassResource),AStudent);
}

Done.WaitOne();
Console.WriteLine("All operations have completed. Press enter to exit");
Console.ReadLine();
}
}
}
posted on 2006-04-29 09:59  共同学习,共同进步  阅读(652)  评论(0编辑  收藏  举报