zoukankan      html  css  js  c++  java
  • 多个线程可能会试图同时访问某个对象。在多个线程同时争相访问某个对象的同时,如果一个线程修改了资源,有些线程可能会收到无效状态。例如,如果某个线程读取对象的字段,同时另一线程正在修改该字段,则第一个线程可能会收到无效的字段状态。这种情况称为竞用情况。

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

    要避免这种情况,可以通过使用锁定,帮助防止代码的关键部分出现竞用情况。锁定由 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();
    }
    }
    }
  • 相关阅读:
    OpenJudge 6042 雇佣兵
    POJ 1741 树上 点的 分治
    Codevs 1695 Windows2013
    复制书稿
    乘积最大
    编辑距离问题
    石子合并
    最大正方形子矩阵
    选菜
    混合背包
  • 原文地址:https://www.cnblogs.com/snowball/p/388352.html
Copyright © 2011-2022 走看看