以下是问题:
假设有3个列表l1,l2& l3长度相同。三个线程访问三个列表。说T1 - > l1,T2 - > l2& T3-> l3。它应按顺序打印说明第一个元素,然后是第二个列表的第一个元素,然后是第三个列表的第一个元素。然后是第一个的第二个元素,然后是第二个列表的第二个元素,然后是第三个列表的第二个元素。
我尝试了什么:
private static readonly Object obj = new Object();
static List<string> list1 = new List<string> { "1", "2", "3", "4" };
static List<string> list2 = new List<string> { "a", "b", "c", "d" };
static List<string> list3 = new List<string> { "*", "+", "-", "?" };
static int i = 0;
static void Main(string[] args)
{
Thread t1 = new Thread(() => PrintItem());
t1.Name = "Print1";
Thread t2 = new Thread(() => PrintItem());
t2.Name = "Print2";
Thread t3 = new Thread(() => PrintItem());
t3.Name = "Print3";
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.Read();
}
private static void PrintItem()
{
while (true)
{
lock (obj)
{
if (i >= list1.Count)
break;
Console.WriteLine(Thread.CurrentThread.Name + " " + list1[i]);
Console.WriteLine(Thread.CurrentThread.Name + " " + list2[i]);
Console.WriteLine(Thread.CurrentThread.Name + " " + list3[i]);
i++;
}
}
}
输出正确,但它不使用三个线程。请更正代码。
答案 0 :(得分:2)
虽然这是一个非常奇怪的要求,但可以使用Monitor.Pulse
和Monitor.Wait
private static readonly Object obj = new Object();
static List<string> list1 = new List<string> { "1", "2", "3", "4" };
static List<string> list2 = new List<string> { "a", "b", "c", "d", "e" };
static List<string> list3 = new List<string> { "*", "+", "-", "?" };
static int i = 0;
//thread synchronization data
const int numThreads = 3;
static int workingCount = 0;
static int lastItem = 0;
static object locker = new object();
static void Main(string[] args)
{
Thread t1 = new Thread(PrintItem);
t1.Name = "Print1";
Thread t2 = new Thread(PrintItem);
t2.Name = "Print2";
Thread t3 = new Thread(PrintItem);
t3.Name = "Print3";
t1.Start(0);
t2.Start(1);
t3.Start(2);
t1.Join();
t2.Join();
t3.Join();
Console.ReadLine();
}
private static void PrintItem(object state)
{
Interlocked.Increment(ref workingCount);
int workingList = (int)state;
int idx = 0;
List<string> list = null;
switch (workingList)
{
case 0:
list = list1;
break;
case 1:
list = list2;
break;
case 2:
list = list3;
break;
}
lock (locker)
do
{
while ((lastItem % numThreads) != workingList)
{
Monitor.Wait(locker);
}
Console.WriteLine("Thread: {0}\tValue: {1}", Thread.CurrentThread.Name, list[idx]);
lastItem++;
Monitor.PulseAll(locker);
} while (++idx < list.Count);
//Handle continuing to pulse until all lists are done.
Interlocked.Decrement(ref workingCount);
lock (locker)
while (workingCount != 0)
{
while ((lastItem % numThreads) != workingList)
Monitor.Wait(locker);
lastItem++;
Monitor.PulseAll(locker);
}
}
}
答案 1 :(得分:1)
如果是我,我会使用EventWaitHandles来发信号并同步你的线程。在我的代码中,Threads等待一个Signal然后打印出他们当前的字符串然后等待再次发出信号:
static void Main(string[] args)
{
List<string> list1 = new List<string> { "1", "2", "3", "4" };
List<string> list2 = new List<string> { "a", "b", "c", "d" };
List<string> list3 = new List<string> { "*", "+", "-", "?" };
using (EventWaitHandle waitHandle1 = new AutoResetEvent(false))
using (EventWaitHandle waitHandle2 = new AutoResetEvent(false))
using (EventWaitHandle waitHandle3 = new AutoResetEvent(false))
using (EventWaitHandle waitHandle4 = new AutoResetEvent(false))
{
Thread t1 = new Thread(() =>
{
ThreadData state = new ThreadData()
{
Name = "Thread1",
Strings = list1,
WaitHandle = waitHandle1,
SignalHandle = waitHandle2
};
PrintItemWhenSignaled(state);
});
Thread t2 = new Thread(() =>
{
ThreadData state = new ThreadData()
{
Name = "Thread2",
Strings = list2,
WaitHandle = waitHandle2,
SignalHandle = waitHandle3
};
PrintItemWhenSignaled(state);
});
Thread t3 = new Thread(() =>
{
ThreadData state = new ThreadData()
{
Name = "Thread3",
Strings = list3,
WaitHandle = waitHandle3,
SignalHandle = waitHandle4
};
PrintItemWhenSignaled(state);
});
t1.Start();
t2.Start();
t3.Start();
for (int index = 0; index < list1.Count; index++)
{
waitHandle1.Set();
waitHandle4.WaitOne(100);
}
}
Console.WriteLine("Press any key...");
Console.ReadKey();
}
private static void PrintItemWhenSignaled(ThreadData threadState)
{
foreach (string value in threadState.Strings)
{
threadState.WaitHandle.WaitOne(100);
Console.WriteLine("{0}:{1}", threadState.Name, value);
threadState.SignalHandle.Set();
}
}
public class ThreadData
{
public string Name { get; set; }
public EventWaitHandle WaitHandle { get; set; }
public EventWaitHandle SignalHandle { get; set; }
public List<string> Strings { get; set; }
}
}
答案 2 :(得分:-1)
因为Lock只有一个线程......第一个是第一个......可以访问你的列表。
删除锁定语句或删除:
if (i >= list1.Count)
break;
条件,或者使用属性ThreadStatic
i
ThreadStatic
如果这是你的预期输出?