private int index = 0;
private object threadlock = new object();
private void button1_Click(object sender, EventArgs e)
{
// 保存1000个文件路径
List<string> lstPath = new List<string>();
for (int i = 0; i < 1000; i++)
{
lstPath.Add("c:\\test\\"+ i.ToString() +".exe");
} index = 0;
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(GetFileData));
threads[i].IsBackground = true;
} foreach (Thread t in threads)
{
t.Start(lstPath);
} foreach (Thread t in threads)
{
t.Join();
}
} private void GetFileData(object objPath)
{
if (objPath == null)
{
return;
} List<string> lstPath = (List<string>)objPath;
if (lstPath == null || lstPath.Count <= 0)
{
return;
} while (true)
{
string strFile = "";
if (index >= lstPath.Count)
{
return;
} // ReadFile阻塞的时间非常长,所以我不想使用lock来同步ReadFile
// 但是,如果不用lock来同步ReadFile,好像数组又不对了
// 我的想法,只有 strFile = lstPath[index] 这行代码涉及到同步处理
// 只要使用lock处理取出正确的path,ReadFile是可以不用lock的吧
// 如果ReadFile也使用了lock,其他线程都必须等待前一个线程结束,才能继续
// 这样不又变成单线程了吗??
lock (threadlock)
{
strFile = lstPath[index];
// ReadFile(strFile);
}
ReadFile(strFile);
}
}
private object threadlock = new object();
private void button1_Click(object sender, EventArgs e)
{
// 保存1000个文件路径
List<string> lstPath = new List<string>();
for (int i = 0; i < 1000; i++)
{
lstPath.Add("c:\\test\\"+ i.ToString() +".exe");
} index = 0;
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(GetFileData));
threads[i].IsBackground = true;
} foreach (Thread t in threads)
{
t.Start(lstPath);
} foreach (Thread t in threads)
{
t.Join();
}
} private void GetFileData(object objPath)
{
if (objPath == null)
{
return;
} List<string> lstPath = (List<string>)objPath;
if (lstPath == null || lstPath.Count <= 0)
{
return;
} while (true)
{
string strFile = "";
if (index >= lstPath.Count)
{
return;
} // ReadFile阻塞的时间非常长,所以我不想使用lock来同步ReadFile
// 但是,如果不用lock来同步ReadFile,好像数组又不对了
// 我的想法,只有 strFile = lstPath[index] 这行代码涉及到同步处理
// 只要使用lock处理取出正确的path,ReadFile是可以不用lock的吧
// 如果ReadFile也使用了lock,其他线程都必须等待前一个线程结束,才能继续
// 这样不又变成单线程了吗??
lock (threadlock)
{
strFile = lstPath[index];
// ReadFile(strFile);
}
ReadFile(strFile);
}
}
第一种情况
lock (threadlock)
{
strFile = lstPath[index++];
}
ReadFile(strFile);第二种情况
lock (threadlock)
{
strFile = lstPath[index++];
ReadFile(strFile);
}第一种情况,数据仍然有错误
第二种情况,数据是正确的
也就是说,为了提高速度,ReadFile是不能加lock了
至于怎么处理线程运行次序是另一回事
不过你的处理也不对,你不能保证每个线程使用不同的文件路径,因为index一直没有变化,所以strFile也不会变化。如果文件不是共享方式,多个线程访问同一个文件会抛出异常。
不参考CPU因素,不参考调度问题的时间损耗
现在共有10个文件,开了10个线程,读一个文件需要10秒
单线程需要100秒读取完
如果是下面第一种情况,只需要10秒
如果是下面第二种情况,还是需要100秒
对吗?lock (threadlock)
{
strFile = lstPath[index++];
}
ReadFile(strFile);第二种情况
lock (threadlock)
{
strFile = lstPath[index++];
ReadFile(strFile);
}
除非你ReadFile里还做了什么事不过你的代码:
if (index >= lstPath.Count)
{
return;
}
应该放到lock里,否则有异常。
{
static List<string> _files;
static int _index = 0;
static object _lock = new object(); static void Main(string[] args)
{
_files = Enumerable.Range(0, 40).Select(i => "File" + i).ToList();
var t1 = new Thread(DoWork);
var t2 = new Thread(DoWork);
t1.Start();
t2.Start();
Console.Read();
} static void DoWork()
{
while (true)
{
var filename = "";
lock (_lock)
{
if (_index >= _files.Count)
return;
filename = _files[_index++];
}
//complex work
Console.WriteLine("Thread[{0}] {1}", Thread.CurrentThread.ManagedThreadId, filename);
Thread.Sleep(200);
}
}
}
按理说代码不需要加锁,请检查其他地方。