C# 多线程,带监视器进入/退出、等待/脉冲、锁定

C# 多线程,带监视器进入/退出、等待/脉冲、锁定,c#,multithreading,monitor,C#,Multithreading,Monitor,我在办公室工作 我只能用班长课。没有信号/信号灯。(是的,这是为学校准备的,但不是家庭作业,只是为我的实践测试做一个免费的练习,我真的需要做好准备,所以让这个项目工作对我帮助很大) 我的问题是,我不知道要“锁定”哪些对象等(正如你所看到的,我已经尝试了很多,只是随机对象) 我有4个线程,1个经销商,3个吸烟者。我有一门商人课和一门吸烟者课。现在,我所有的吸烟者都去Monitor.Wait()那里,喝了一两杯烟,然后他们再也出不来了,即使每次经销商把烟放在桌子上,我都会打电话给Monitor.Pu

我在办公室工作

我只能用班长课。没有信号/信号灯。(是的,这是为学校准备的,但不是家庭作业,只是为我的实践测试做一个免费的练习,我真的需要做好准备,所以让这个项目工作对我帮助很大)

我的问题是,我不知道要“锁定”哪些对象等(正如你所看到的,我已经尝试了很多,只是随机对象)

我有4个线程,1个经销商,3个吸烟者。我有一门商人课和一门吸烟者课。现在,我所有的吸烟者都去Monitor.Wait()那里,喝了一两杯烟,然后他们再也出不来了,即使每次经销商把烟放在桌子上,我都会打电话给Monitor.Pulsell()。我想这是因为我使用了错误的对象作为参数,我完全不知道

文本框和字符串主要用于在我的WPF类中给出数据

吸烟类:请原谅德语变量名。(烟草=烟草,纸张=纸张,施特雷赫=火焰,朱塔=烟熏,劳赫泽特=烟熏时间)

经销商类别:

class Dealer
{
    public static Random r = new Random();
    public Boolean tabak = false;
    public Boolean papier = false;
    public Boolean streichhölzer = false;
    public String zutaten;

    public Boolean isEmpty()
    {
        return !(tabak || papier || streichhölzer);
    }

    public void setTabak()
    {
        tabak = true;
    }

    public void setPapier()
    {
        papier = true;
    }

    public void setStreichhölzer()
    {
        streichhölzer = true;
    }

    public void takeTabak()
    {
        tabak = false;
    }

    public void takePapier()
    {
        papier = false;
    }

    public void takeStreichhölzer()
    {
        streichhölzer = false;
    }

    TextBox status;

    public Dealer(TextBox status)
    {
        this.status = status;
    }

    public static readonly object _locker = new object();

    public void Go()
    {
        while (true)
        {
            if (isEmpty())
            {
                lock (this)
                {
                    if (!tabak && !papier && !streichhölzer)
                    {
                        int zahl1 = r.Next(0, 3);
                        int zahl2 = r.Next(0, 3);
                        while (zahl1 == zahl2)
                        {
                            zahl2 = r.Next(0, 3);
                        }
                        switch (zahl1)
                        {
                            case (0):
                                setTabak();
                                break;
                            case (1):
                                setPapier();
                                break;
                            case (2):
                                setStreichhölzer();
                                break;
                        }
                        switch (zahl2)
                        {
                            case (0):
                                setTabak();
                                break;
                            case (1):
                                setPapier();
                                break;
                            case (2):
                                setStreichhölzer();
                                break;
                        }
                        updateText();
                        Monitor.PulseAll(this);
                    }
                }
            }
        }
    }

    public void updateText()
    {
        try
        {
            status.Dispatcher.BeginInvoke(
              System.Windows.Threading.DispatcherPriority.Normal
              , new System.Windows.Threading.DispatcherOperationCallback(delegate
              {
                  zutaten = "";
                  if (tabak)
                  {
                      zutaten += " Tabak ";
                  }
                  if (papier)
                  {
                      zutaten += " Papier ";
                  }
                  if (streichhölzer)
                  {
                      zutaten += " Streichhölzer ";
                  }
                  status.Text = zutaten;
                  status.UpdateLayout();
                  return null;
              }), null);
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.ToString());
        }
    }
}

有几件事不对:

  • 吸烟者和商人都有自己的储物柜物品。如果Smoker和Dealer线程不以某种方式访问相同的同步原语,则不会发生同步

  • 在Dealer中,您锁定“this”,并对其进行脉冲。它是没有意义的,因为没有其他线程会知道它,因为只有一个线程(经销商)使用它

  • 锁定“this”或公共属性/字段是错误的做法。在大型软件项目中,这样的实践很容易导致死锁的情况

  • 不要让每个类使用彼此的同步对象。只需让经销商拥有一个同步对象,吸烟者使用该对象同步访问经销商资源。但实际上,让多个类与同步对象混淆也是一种非常糟糕的做法

  • 更好的方法是在Dealer类中有一个私有同步对象,并以这种方式实现应用程序逻辑,这样同步只能在Dealer类内部处理,对任何吸烟者都是完全透明的


  • 它是否真的在方法名中使用德语Umlauts进行编译,比如“setstreichölzer”@elgonzo确实如此,尽管我发现标识符中的非ASCII字符由于不同的原因是不可取的。不过,C#有Unicode标识符,默认情况下,.cs文件是UTF8。非常感谢您的回复。我还在学习,现在我明白了锁定对象是如何工作的。我将尝试按照您在第4节中描述的那样现在就做。因为我的时间,当我找到更多的时间时,我会按照你在5中所描述的那样去做。将让您知道它是否有效,提前感谢:)
    class Dealer
    {
        public static Random r = new Random();
        public Boolean tabak = false;
        public Boolean papier = false;
        public Boolean streichhölzer = false;
        public String zutaten;
    
        public Boolean isEmpty()
        {
            return !(tabak || papier || streichhölzer);
        }
    
        public void setTabak()
        {
            tabak = true;
        }
    
        public void setPapier()
        {
            papier = true;
        }
    
        public void setStreichhölzer()
        {
            streichhölzer = true;
        }
    
        public void takeTabak()
        {
            tabak = false;
        }
    
        public void takePapier()
        {
            papier = false;
        }
    
        public void takeStreichhölzer()
        {
            streichhölzer = false;
        }
    
        TextBox status;
    
        public Dealer(TextBox status)
        {
            this.status = status;
        }
    
        public static readonly object _locker = new object();
    
        public void Go()
        {
            while (true)
            {
                if (isEmpty())
                {
                    lock (this)
                    {
                        if (!tabak && !papier && !streichhölzer)
                        {
                            int zahl1 = r.Next(0, 3);
                            int zahl2 = r.Next(0, 3);
                            while (zahl1 == zahl2)
                            {
                                zahl2 = r.Next(0, 3);
                            }
                            switch (zahl1)
                            {
                                case (0):
                                    setTabak();
                                    break;
                                case (1):
                                    setPapier();
                                    break;
                                case (2):
                                    setStreichhölzer();
                                    break;
                            }
                            switch (zahl2)
                            {
                                case (0):
                                    setTabak();
                                    break;
                                case (1):
                                    setPapier();
                                    break;
                                case (2):
                                    setStreichhölzer();
                                    break;
                            }
                            updateText();
                            Monitor.PulseAll(this);
                        }
                    }
                }
            }
        }
    
        public void updateText()
        {
            try
            {
                status.Dispatcher.BeginInvoke(
                  System.Windows.Threading.DispatcherPriority.Normal
                  , new System.Windows.Threading.DispatcherOperationCallback(delegate
                  {
                      zutaten = "";
                      if (tabak)
                      {
                          zutaten += " Tabak ";
                      }
                      if (papier)
                      {
                          zutaten += " Papier ";
                      }
                      if (streichhölzer)
                      {
                          zutaten += " Streichhölzer ";
                      }
                      status.Text = zutaten;
                      status.UpdateLayout();
                      return null;
                  }), null);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }
    }