关于哲学家进餐问题的多线程实现

zyjisdog 2014-05-25 04:41:44
Form1.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace 哲学家进餐问题
{
public partial class Form1 : Form
{
private Thread[] phiThreads;
private Chopsticks[] chopsticks;
private Random random;
private object SyncObject;
delegate void SetTextCallback(ListBox control, string text);

public Form1()
{
InitializeComponent();
init();
}

private void 停止_Click(object sender, EventArgs e)
{
abort();
}

private void 开始_Click(object sender, EventArgs e)
{
for (int i = 0; i < 5; i++)//初始化5个哲学家,执行phiAction方法
{
phiThreads[i] = new Thread(new ParameterizedThreadStart(phiAction));
phiThreads[i].Name = i.ToString();
phiThreads[i].Start(i);
}
}

private void 退出_Click(object sender, EventArgs e)
{
Application.Exit();
}

private void UpdateListBox(ListBox control, string text)
{
SyncObject = new object();
if (control.InvokeRequired) //用于在Listbox中添加text
{
SetTextCallback d = new SetTextCallback(UpdateListBox);
this.Invoke(d, new object[] { control, text });
}
else
{
lock (SyncObject)
{
control.Items.Add(text);
}
}
}
private void print(int who,string str)
{

string printStr = who.ToString() + str;
lock(this)
{

UpdateListBox(listBox1, printStr); //在Listbox中添加条目
}
}

private void init()
{
phiThreads = new Thread[5];
chopsticks = new Chopsticks[5];
random = new Random();
}

private void abort()
{
for (int i = 0;i<5;i++)
{
phiThreads[i].Abort();//结束线程
}
}
private void phiAction(object index)
{

while(true)
{
Thinking(index);
Waiting(index);
Eating(index);

int sleepTime = random.Next(100, 500);
Thread.Sleep(sleepTime + 500);
}
}

private void Thinking(object index)
{

print((int)index, " is thinking...");

int sleepTime = random.Next(100, 500);
Thread.Sleep(sleepTime + 500);

}

private void Eating(object index)
{
print((int)index, " is eating...");

int sleepTime = random.Next(100, 500);
Thread.Sleep(sleepTime + 500);

chopsticks[(int)index].chopsSem.Release(); //释放右边的筷子
chopsticks[((int)index+1) % 5].chopsSem.Release(); //释放左边的筷子

}

private void Waiting(object index)
{
print((int)index, " is waiting...");

int sleepTime = random.Next(100, 500);
Thread.Sleep(sleepTime + 500);

if ((int)index % 2 == 0)//偶数号哲学家
{
chopsticks[(int)index].chopsSem.WaitOne(); //获取右边的筷子
chopsticks[(int)index + 1 % 5].chopsSem.WaitOne(); //获取左边的筷子
}
else//奇数号哲学家
{
chopsticks[(int)index + 1 % 5].chopsSem.WaitOne(); //获取左边的筷子
chopsticks[(int)index].chopsSem.WaitOne(); //获取右边的筷子
}
}
}


}


Chopsticks类:
public class Chopsticks
{
public Semaphore chopsSem;
Chopsticks()
{
chopsSem = new Semaphore(1, 1);
}

}


运行的时候,当5个哲学家都开始waiting的时候就会出现:未将对象引用设置到对象的实例。

我不知道是哪里出错了。。。请麻烦帮我分析下,谢谢了!!
...全文
481 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
ima_zhan 2014-05-28
  • 打赏
  • 举报
回复
引用 15 楼 zengzhengyou 的回复:
[quote=引用 13 楼 moranhuoshou 的回复:] [quote=引用 10 楼 zengzhengyou 的回复:] [quote=引用 9 楼 moranhuoshou 的回复:] 楼上BBYY 说了一堆 看着烦躁。。。。
素质,你说得出来么。[/quote] 我承认我说不出来,我也不可能几乎每个帖子都回帖,然后一堆举例推断,我知道他流弊,但是我很反感这样说了一堆“废话”又不厌其烦还自得所乐却又迷惑大众的“大神”。[/quote] 总要有一些人是回帖贴代码,有些人是说些底层原理, 比如渣如我现在就更喜欢看原理性的东西,代码的东西,随便百度,谷歌一搜索出来都是一群,总能找到自己想要的 但是没有两个说出了原理性的东西, 正如很多书籍一样都是写出了“怎么做” 而没有解释“为什么这么做” 正如P哥所说的东西是他这么多年所总结的一些经验性的东西,是一些常见书籍所没有的 也许你看他没有贴代码,但是他给出了方向,方案。[/quote] 严重同意,很喜欢看他的回复
信不信由你zzy 2014-05-28
  • 打赏
  • 举报
回复
引用 13 楼 moranhuoshou 的回复:
[quote=引用 10 楼 zengzhengyou 的回复:] [quote=引用 9 楼 moranhuoshou 的回复:] 楼上BBYY 说了一堆 看着烦躁。。。。
素质,你说得出来么。[/quote] 我承认我说不出来,我也不可能几乎每个帖子都回帖,然后一堆举例推断,我知道他流弊,但是我很反感这样说了一堆“废话”又不厌其烦还自得所乐却又迷惑大众的“大神”。[/quote] 总要有一些人是回帖贴代码,有些人是说些底层原理, 比如渣如我现在就更喜欢看原理性的东西,代码的东西,随便百度,谷歌一搜索出来都是一群,总能找到自己想要的 但是没有两个说出了原理性的东西, 正如很多书籍一样都是写出了“怎么做” 而没有解释“为什么这么做” 正如P哥所说的东西是他这么多年所总结的一些经验性的东西,是一些常见书籍所没有的 也许你看他没有贴代码,但是他给出了方向,方案。
  • 打赏
  • 举报
回复
引用 13 楼 moranhuoshou 的回复:
[quote=引用 10 楼 zengzhengyou 的回复:] [quote=引用 9 楼 moranhuoshou 的回复:] 楼上BBYY 说了一堆 看着烦躁。。。。
素质,你说得出来么。[/quote] 我承认我说不出来,我也不可能几乎每个帖子都回帖,然后一堆举例推断,我知道他流弊,但是我很反感这样说了一堆“废话”又不厌其烦还自得所乐却又迷惑大众的“大神”。[/quote] 很多人很反感sp,认为这胖子唧唧歪歪了半天,根本不知道他说的是什么 还有很多人觉得sp特NB,因为虽然他的回答根本没解决问题,甚至回答跟问题就是风马牛不相及、牛头不对马嘴,但他给出的是他对这个问题的看法,给的是思路,而解决问题,要的就是思路,一条思路走不通了,就要换一条思路 顺带说下,真心很少会看到他直接给代码。。。。
SeeYou孙悟空 2014-05-27
  • 打赏
  • 举报
回复
引用 10 楼 zengzhengyou 的回复:
[quote=引用 9 楼 moranhuoshou 的回复:] 楼上BBYY 说了一堆 看着烦躁。。。。
素质,你说得出来么。[/quote] 我承认我说不出来,我也不可能几乎每个帖子都回帖,然后一堆举例推断,我知道他流弊,但是我很反感这样说了一堆“废话”又不厌其烦还自得所乐却又迷惑大众的“大神”。
gengchenhui 2014-05-26
  • 打赏
  • 举报
回复
引用 9 楼 moranhuoshou 的回复:
楼上BBYY 说了一堆 看着烦躁。。。。
楼上有你学不到的精髓。
信不信由你zzy 2014-05-26
  • 打赏
  • 举报
回复
引用 9 楼 moranhuoshou 的回复:
楼上BBYY 说了一堆 看着烦躁。。。。
素质,你说得出来么。
SeeYou孙悟空 2014-05-26
  • 打赏
  • 举报
回复
楼上BBYY 说了一堆 看着烦躁。。。。
zyjisdog 2014-05-26
  • 打赏
  • 举报
回复
已经在推倒重写了。。
  • 打赏
  • 举报
回复
当然如果仔细核对设计蓝图的细节,可能“只要第二个筷子的事件监听也触发了,就可以开始吃饭了”这句话需要加上一个操作,“只要第二个筷子的事件监听也触发了,就可以注销两个筷子的事件监听,然后开始吃饭了”。 结果,这个“哲学家”对象其实代码很简单,而且里边也没有任何一行while循环、和Sleep阻塞。它只有两个Timer分别触发“发呆”和“吃饭”的起停;它知道“左筷子”和“右筷子”属性的值,并且会在适当的时候监听其抛出的时间,或者在适当的时候注销这个监听。 而“筷子”对象其实更简单,就是能够在自己被放到桌子上时抛出事件通知即可。 传统的“哲学家进餐问题”看似简单,但是死板,于是你很容易进入多线程编程的死胡同。使用现代的“哲学家进餐问题”模型你才能更好地进行多线程程序设计,其中的关键就是“不要有while循环,不要有阻塞代码”。
  • 打赏
  • 举报
回复
引用 5 楼 zyjisdog 的回复:
我只是想学习下多线程而已啊。。
只学会了某种编程语言语法,没有学过画流程图、类图、时序图、状态图等软件语言? 遗憾!
  • 打赏
  • 举报
回复
所谓“哲学家进餐问题”的程序,被一些国内的古老的教科书写歪了。别忘记了这个问题提出时的时代,那时候是多么原始,面向对象技术甚至都没有成型。 “哲学家”如果进入发呆想MM状态,也许你可以用一个thread.sleep。(但是更好地是使用timer来控制,以便释放系统线程资源) 然后发呆结束时,“哲学家”等待左边的筷子,这绝对不能用一个阻塞式的thread.sleep。你针对“筷子对象”的事件注册一个处理方法就行了。针对右边的筷子也是一样。只要第二个筷子的事件监听也触发了,就可以开始吃饭了。 吃饭也可以用一个thread.sleep。当然同样更好地可以使用timer来代替。 吃完饭就放下左右两只筷子(对于筷子来说,它们就在自己内部触发了事件),然后又开始发呆想MM了。 总之,你会发现你删除掉了 waiting 阻塞,就让程序简单清晰了许多。而一旦你用“事件驱动流程”概念来进行设计,代替了愚蠢地“用while死循环来模拟事件监听操作”,你的代码又离简单高效和容易维护的目标迈进了一大步。 许多传统的代码,特别是上世纪90年代在java中出现的许多代码,都在多线程编程方面释放许多糟粕。因为它缺乏“事件驱动”基本设计。
zyjisdog 2014-05-25
  • 打赏
  • 举报
回复
我只是想学习下多线程而已啊。。
  • 打赏
  • 举报
回复
代码太多,没时间看。 这算法需要用线程?用了线程,就要WaitOne? 把你的代码暂时忘掉,说一下你的程序流程吧。程序设计首先能够画个流程图、类图、时序图、状态图之类的,就够了,就能够看出你的设计是否跟多线程编程相适配了。用不着写代码。
EdsionWang 2014-05-25
  • 打赏
  • 举报
回复
这句代码可出现了不止一次。。。数组超出索引,你可以加断点调试看看index的值是多少
zyjisdog 2014-05-25
  • 打赏
  • 举报
回复
引用 1 楼 andywangguanxi 的回复:
停在哪一句上了?
停在chopsticks[(int)index].chopsSem.WaitOne(); //获取右边的筷子
EdsionWang 2014-05-25
  • 打赏
  • 举报
回复
停在哪一句上了?

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧