关于线程间同步的问题,紧急求助!我有一个类,主要是操作一个List<T>.
这个类有若干个方法:
比如向List中插入:ADD();
从List中删除:Remove();
枚举List中的数据:GetByXX1();GetByXX2();GetByXX3();而这些方法都可以是被多线程并发执行的。
因为List不是线程安全的。
所以加锁是避免不了的了。
但是如果每个方法都加了锁,那就全变成同步执行的了。我希望插入删除这些操作同步,而读取操作并行。
应该怎么做呢?项目最后一天,大家帮忙!
这个类有若干个方法:
比如向List中插入:ADD();
从List中删除:Remove();
枚举List中的数据:GetByXX1();GetByXX2();GetByXX3();而这些方法都可以是被多线程并发执行的。
因为List不是线程安全的。
所以加锁是避免不了的了。
但是如果每个方法都加了锁,那就全变成同步执行的了。我希望插入删除这些操作同步,而读取操作并行。
应该怎么做呢?项目最后一天,大家帮忙!
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;namespace WindowsApplication78
{
public partial class Form1 : Form
{
int i = 0;
List<String> L = new List<string>();
ListBox LB1 = new ListBox();
ListBox LB2 = new ListBox(); public Form1()
{
InitializeComponent(); LB1.Parent = this; LB2.Parent = this;
LB2.Location = new Point(150, 0); this.Shown += new EventHandler(Form1_Shown);
} void Form1_Shown(object sender, EventArgs e)
{
Thread T = new Thread(new ThreadStart(Write));
T.IsBackground = true;
T.Start();
T = new Thread(new ThreadStart(Read1));
T.IsBackground = true;
T.Start();
T = new Thread(new ThreadStart(Read2));
T.IsBackground = true;
T.Start();
} void Write()
{
try
{
while (true)
if (Monitor.TryEnter(L))
{
L.Add(i++.ToString());
Monitor.Exit(L);
Thread.Sleep(100);
}
}
catch
{
// 忽略程序退出的异常
}
} delegate void ReadToListBox(String S); void Read1()
{
try
{
while (true)
if (Monitor.TryEnter(L))
{
if (L.Count > 0)
{
String S = L[L.Count - 1];
L.RemoveAt(L.Count - 1);
this.Invoke(new ReadToListBox(DoReadToListBox1), new Object[] { S });
}
Monitor.Exit(L);
}
}
catch
{
// 忽略程序退出的异常
}
} void Read2()
{
try
{
while (true)
if (Monitor.TryEnter(L))
{
if (L.Count > 0)
{
String S = L[L.Count - 1];
L.RemoveAt(L.Count - 1);
this.Invoke(new ReadToListBox(DoReadToListBox2), new Object[] { S });
}
Monitor.Exit(L);
}
}
catch
{
// 忽略程序退出的异常
}
} void DoReadToListBox1(String S)
{
LB1.Items.Add(S);
LB1.SelectedIndex = LB1.Items.Count - 1;
LB1.Invalidate();
} void DoReadToListBox2(String S)
{
LB2.Items.Add(S);
LB2.SelectedIndex = LB2.Items.Count - 1;
LB2.Invalidate();
}
}
}
有点不明白请教一下!1.如果把Monitor.TryEnter(L) 改成
Monitor.Enter(L) 并且把while (true)
去掉,效果是不是一样的?2.你的代码里,Read1 和 Read2 是不是同步的?
也就是说Read1获得了锁,Read2必须等待?
但是读写锁本身的效率不如Monitor,所以如果写入量也不小的话,效率反而会比较低
如果你只是想读一次,然后退出线程,那是可以不用while,然后用Monitor.Enter等待获得锁,然后读一次就结束了2.read1进入moniter.tryenter开始的互斥区后,read2就是等待,直到read1的moniter.exit释放互斥锁
互斥是针对共享的资源,比如这里的list,某一时间只有一个线程能访问,其他要等待,同步针对是线程间,比如这里要先写入,有数据后才能读出来
这里你如果读不用锁,那执行的流程就是不可预知的,就不是原子操作read1执行完
String S = L[L.Count - 1];
L.RemoveAt(L.Count - 1);
时间片轮到read2了,
read2这时刚好接上次执行到
String S = L[L.Count - 1];
接下来执行
L.RemoveAt(L.Count - 1);
了一下,那就是删2次了,那数据要么就丢失,要么就是L.Count - 1=-1超出索引
http://www.cnblogs.com/lucifer1982/archive/2008/12/07/1349437.html
ReaderWriterLockSlim 正式解决我的问题的方法。