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();
    }
    }
    }
  • 相关阅读:
    Codechef EDGEST 树套树 树状数组 线段树 LCA 卡常
    BZOJ4319 cerc2008 Suffix reconstruction 字符串 SA
    Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal
    Codeforces 316G3 Good Substrings 字符串 SAM
    Codechef CHSIGN Change the Signs(May Challenge 2018) 动态规划
    BZOJ1396 识别子串 字符串 SAM 线段树
    CodeForces 516C Drazil and Park 线段树
    CodeForces 516B Drazil and Tiles 其他
    CodeForces 516A Drazil and Factorial 动态规划
    SPOJ LCS2
  • 原文地址:https://www.cnblogs.com/snowball/p/388352.html
Copyright © 2011-2022 走看看