草庐IT

C# 线程 : Using Monitor. 等待、锁定和 PulseAll

coder 2024-05-21 原文

我是 CSharp 和线程的新手。

为了熟悉Monitor.Wait、Monitor.lock和Monitor.PulseAll,我构建了一个场景描述如下。

<我> “一个 FootballGround 由不同的球队共享用于练习目的。任何时候只有一个球队可以使用 field 进行练习。一个团队可以使用 field 进行 30 分钟的练习。一旦时间达到 25 分钟,它应该向其他球队发出信号地面将在 5 分钟后释放的线程。本地面潮湿时(枚举有三个值 free、alloted、wet)不允许任何团队锁定地面,所有人都应等待 10 分钟”

老实说,我不知道如何将描述转化为实际编码。根据我的理解,我设计了大纲。

namespace ThreadingSimulation
 {

  // A Random Activity can be picked up from this enum by a team

         public enum RandomGroundStatus
         {
             free,
             allotted,
             Wet          
         }

class FootBallGround
{

    public void Playing(object obj)
    {
      // Here the name of the team which is using the  ground will be printed
      // Once the time is reached to 25 minnutes the active thread acquired
      // the lock will signal  other threads    

    }

   public void GroundCleaningInProgress(object obj)
   {

      // Ground cleaning is in progress all of you
      // wait for 10 minutes

   }

}    




 class Team
   {
     string teamName;  

      static void Main()
      {

        //select random value for GrandStatus from enum

       // if the ground is wet no team is allowed to get the
       // ground for 10 minutes  

        //if the ground is free "Team A" locks the ground

        // otherwise "Team B" locks the ground

      }

   }

}

这里我不知道如何应用锁和信号。请帮助我。

最佳答案

实际上,您的场景并没有很大程度地映射到 - 但无论如何我们都会尝试;-p

我稍微调整了设置;相反:

  • 一次可以有一个实体
  • 当一个团队完成后,他们会告诉他们看到的第一个人(如果有人在等)
  • 当清洁工结束时,他们很吵 - 所以每个人都注意到他们离开并试图上场

这是代码;请注意,他们在使用 field 时没有锁,因为那样会阻止其他人加入 Pulse 队列。

实际上,我们可以用 lock 完成所有这些操作(根本不使用 Pulse) ,并且只使用标准的阻塞行为。但此示例显示 PulsePulseAll 用于在满足条件时重新激活线程。

using System;
using System.Threading;
interface IGroundUser
{
    bool Invoke(); // do your stuff; return true to wake up *everyone*
                   // afterwards, else false
}
class Team : IGroundUser
{
    private readonly string name;
    public Team(string name) { this.name = name; }
    public override string ToString() { return name; }
    public bool Invoke()
    {
        Console.WriteLine(name + ": playing...");
        Thread.Sleep(25 * 250);
        Console.WriteLine(name + ": leaving...");
        return false;
    }
}
class Cleaner : IGroundUser
{
    public override string ToString() {return "cleaner";}
    public bool Invoke()
    {
        Console.WriteLine("cleaning in progress");
        Thread.Sleep(10 * 250);
        Console.WriteLine("cleaning complete");
        return true;
    }
}
class FootBallGround
{
    static void Main()
    {
        var ground = new FootBallGround();
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team A")); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team B")); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Cleaner()); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team C")); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team D")); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team E")); });
        Console.ReadLine();

    }
    bool busy;
    private readonly object syncLock = new object();
    public void UseGrounds(IGroundUser newUser)
    {
        // validate outside of lock
        if (newUser == null) throw new ArgumentNullException("newUser");
        // only need the lock when **changing** state
        lock (syncLock)
        {
            while (busy)
            {
                Console.WriteLine(newUser + ": grounds are busy; waiting...");
                Monitor.Wait(syncLock);
                Console.WriteLine(newUser + ": got nudged");
            }
            busy = true; // we've got it!
        }
        // do this outside the lock, allowing other users to queue
        // waiting for it to be free
        bool wakeAll = newUser.Invoke();

        // exit the game
        lock (syncLock)
        {
            busy = false;
            // wake up somebody (or everyone with PulseAll)
            if (wakeAll) Monitor.PulseAll(syncLock);
            else Monitor.Pulse(syncLock);
        }
    }    
}    

关于C# 线程 : Using Monitor. 等待、锁定和 PulseAll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1565240/

有关C# 线程 : Using Monitor. 等待、锁定和 PulseAll的更多相关文章

  1. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. ruby - 如何让Ruby捕获线程中的语法错误 - 2

    我正在尝试使用ruby​​编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?

  6. ruby - 如何在 ruby​​ 中运行后台线程? - 2

    我是ruby​​的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp

  7. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  8. ruby - Rails 开发服务器、PDFKit 和多线程 - 2

    我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它:

  9. ruby - Ruby 1.9.1 中的 native 线程,对我有什么好处? - 2

    所以,Ruby1.9.1现在是declaredstable.Rails应该与它一起工作,并且正在慢慢地将gem移植到它。它具有native线程和全局解释器锁(GIL)。自从GIL到位后,原生线程是否比1.9.1中的绿色线程有任何优势? 最佳答案 1.9中的线程是原生的,但它们被“放慢了速度”,一次只允许一个线程运行。这是因为如果线程真的并行运行,它会混淆现有代码。优点:IO现在在线程中是异步的。如果一个线程阻塞在IO上,那么另一个线程将继续执行直到IO完成。C扩展可以使用真正的线程。缺点:任何非线程安全的C扩展都可能存在使用Thre

  10. ruby - 使写入文件线程安全 - 2

    我在一个ruby​​文件中有一个函数可以像这样写入一个文件File.open("myfile",'a'){|f|f.puts("#{sometext}")}这个函数在不同的线程中被调用,使得像上面这样的文件写入不是线程安全的。有谁知道如何以最简单的方式使这个文件写入线程安全?更多信息:如果重要的话,我正在使用rspec框架。 最佳答案 您可以通过File#flock给锁File.open("myfile",'a'){|f|f.flock(File::LOCK_EX)f.puts("#{sometext}")}

随机推荐