多线程同步
在C#中,可以利用Monitor类等方式实现多线程的同步。Monitor类提供了与lock类相似的共功能,通过向单个线程授予对象锁控制对该对象的访问。Monitor类的Pulse()方法和PulseAll()方法向一个或多个等待的线程发送信号,该信号通知等待线程锁定对的状态已更改,并且锁的所有者准备释放该锁。等待线程被放置在对象的就绪队列中以便最后接收对象锁,一旦线程拥有了锁,就可以检测对象的新状态,以查看是否达到所需状态。Wait()方法则释放对象上的锁以便允许其他线程锁定和访问该对象。在其他线程访问对象时,该调用线程将一直处于等待状态。
例子:生产者消费者问题
生产一个苹果,放在商店中一个,出售一个苹果,商店中苹果少一个,最多生产10个。要求:1、生产者不断将数据放入共享的缓冲;2、消费者不断从共享的缓冲中取出数据;3、生产者必须等消费者取走数据后才能再放新数据(不覆盖数据);4、消费者必须等生产者放入新数据后才能去取(不重复)。
界面
代码如下所示:
using System.Windows.Forms;
using System.Threading;
namespace Lock
{
public partial class Form6 : Form
{
static object apple = new object();//创建一个互斥体,即苹果对象
int maxApple = 10;//最大生产数量
int produceApple = 0;//生产数量
int consumeApple = 0;//消费数量
bool flag = false;//标记是否已经生产结束
Thread tProduce = null;
Thread tConsume = null;
public Form6()
{
InitializeComponent();
}
//生成苹果线程调用
private void Produce()
{
while (!flag)
{
lock (apple)
for (int i = 1; i <= maxApple; i++)
{
//生产苹果
if (this.InvokeRequired)
{
this.Invoke(new Action(() =>
{
this.listBoxProduce.Items.Add(i.ToString());
}));
}
else
{
this.listBoxProduce.Items.Add(i.ToString());
}
produceApple++;
//生产的苹果放到商店
if (this.InvokeRequired)
{
this.Invoke(new Action(() =>
{
this.appleStore.Text = produceApple.ToString();
}));
}
else
{
this.appleStore.Text = produceApple.ToString();
}
if (i == maxApple)
{
this.Invoke(new Action(() =>
{
this.listBoxProduce.Items.Add("苹果生产完了");
}));
flag = true;
}
Thread.Sleep(500);
Monitor.Pulse(apple);
Monitor.Wait(apple);
}
}
}
//消费苹果线程调用
private void Consume()
{
while (true)
{
lock (apple)
{
consumeApple = consumeApple + produceApple;
if (this.InvokeRequired)
{
this.Invoke(new Action(() =>
{
this.listBoxConsume.Items.Add(consumeApple.ToString());
}));
}
else
{
this.listBoxConsume.Items.Add(consumeApple.ToString());
}
produceApple--;
if (this.InvokeRequired)
{
this.Invoke(new Action(() =>
{
this.appleStore.Text = produceApple.ToString();
}));
}
else
{
this.appleStore.Text = produceApple.ToString();
}
if (flag)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() =>
{
this.listBoxConsume.Items.Add("苹果卖完了");
}));
}
else
{
this.listBoxConsume.Items.Add("苹果卖完了");
}
}
Thread.Sleep(500);
Monitor.Pulse(apple);
Monitor.Wait(apple);
}
}
}
private void btn_Start_Click(object sender, EventArgs e)
{
tProduce = new Thread(new ThreadStart(Produce));
tConsume = new Thread(new ThreadStart(Consume)); ;
tProduce.Start();
tConsume.Start();
btn_Start.Enabled = false;
btn_Stop.Enabled = true;
}
private void btn_Stop_Click(object sender, EventArgs e)
{
tProduce.Abort();
tConsume.Abort();
btn_Start.Enabled = true;
btn_Stop.Enabled = false;
this.listBoxProduce.Items.Clear();
this.listBoxConsume.Items.Clear();
this.appleStore.Text = "0";
flag = false;
produceApple = 0;
consumeApple = 0;
}
private void Form6_FormClosing(object sender, FormClosingEventArgs e)
{
if (tProduce != null)
{ tProduce.Abort(); }
if (tConsume != null)
{
{ tConsume.Abort(); }
}
}
}
}