xav*_*ier 4 c# multithreading new-operator
我正在尝试理解多线程的基础知识,所以我构建了一个小程序,提出了一些问题,我会感谢任何帮助:)
这是一个小程序:
class Program
{
public static int count;
public static int max;
static void Main(string[] args)
{
int t = 0;
DateTime Result;
Console.WriteLine("Enter Max Number : ");
max = int.Parse(Console.ReadLine());
Console.WriteLine("Enter Thread Number : ");
t = int.Parse(Console.ReadLine());
count = 0;
Result = DateTime.Now;
List<Thread> MyThreads = new List<Thread>();
for (int i = 1; i < 31; i++)
{
Thread Temp = new Thread(print);
Temp.Name = i.ToString();
MyThreads.Add(Temp);
}
foreach (Thread th in MyThreads)
th.Start();
while (count < max)
{
}
Console.WriteLine("Finish , Took : " + (DateTime.Now - Result).ToString() + " With : " + t + " Threads.");
Console.ReadLine();
}
public static void print()
{
while (count < max)
{
Console.WriteLine(Thread.CurrentThread.Name + " - " + count.ToString());
count++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我通过一些测试运行检查了这个:
我将最大数量设为100,似乎最快的执行时间是2个线程,比10个线程的时间快80%.
问题:
1)线程4-10甚至不打印一次,怎么会这样?
2)不应该更多的线程更快?
我将最大数量设为10000并禁用打印.
使用此配置,5个线程似乎是最快的.
为什么与第一次检查相比有变化?
而且在这种配置中(带打印)所有线程都会打印几次.为什么与第一次打印不同,只打印了几个线程?
有没有办法让所有线程逐个打印?在一条线或类似的东西?
非常感谢您的帮助 :)
您的代码肯定是进入线程世界的第一步,您刚刚经历了第一次(很多)头痛!
首先,static可以使您能够在线程之间共享变量,但它不以线程安全的方式执行.这意味着您的count < max表达count++并不保证是最新的或线程之间的有效保护.当max我的8处理器工作站上只有10(t设置为4)时,查看程序的输出:
T0 - 0
T0 - 1
T0 - 2
T0 - 3
T1 - 0 // wait T1 got count = 0 too!
T2 - 1 // and T2 got count = 1 too!
T2 - 6
T2 - 7
T2 - 8
T2 - 9
T0 - 4
T3 - 1 // and T3 got count = 1 too!
T1 - 5
Run Code Online (Sandbox Code Playgroud)
关于每个线程逐个打印的问题,我假设您正在尝试协调访问count.您可以使用同步原语(例如lockC#中的语句)来完成此操作.以下是对代码的简单修改,它将确保仅max发生增量:
static object countLock = new object();
public static void printWithLock()
{
// loop forever
while(true)
{
// protect access to count using a static object
// now only 1 thread can use 'count' at a time
lock (countLock)
{
if (count >= max) return;
Console.WriteLine(Thread.CurrentThread.Name + " - " + count.ToString());
count++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个简单的修改使您的程序在逻辑上正确,但也很慢.该示例现在出现了一个新问题:锁争用.每个线程现在都在争夺访问权限countLock.我们已经使程序线程安全,但没有并行性的任何好处!
线程和并行性并不是特别容易实现,但幸运的是.Net的最新版本带有任务并行库(TPL)和并行LINQ(PLINQ).
图书馆的美妙之处在于转换当前代码是多么容易:
var sw = new Stopwatch();
sw.Start();
Enumerable.Range(0, max)
.AsParallel()
.ForAll(number =>
Console.WriteLine("T{0}: {1}",
Thread.CurrentThread.ManagedThreadId,
number));
Console.WriteLine("{0} ms elapsed", sw.ElapsedMilliseconds);
// Sample output from max = 10
//
// T9: 3
// T9: 4
// T9: 5
// T9: 6
// T9: 7
// T9: 8
// T9: 9
// T8: 1
// T7: 2
// T1: 0
// 30 ms elapsed
Run Code Online (Sandbox Code Playgroud)
上面的输出是一个有趣的例子,说明为什么线程会为新用户产生"意外结果".当线程并行执行时,它们可以在不同的时间点完成代码块,或者一个线程可能比另一个线程更快.你永远不会真正了解线程!
| 归档时间: |
|
| 查看次数: |
601 次 |
| 最近记录: |