JAN*_*JAN 3 .net c# multithreading
考虑一下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Multithreading
{
class Program
{
static int result = 0;
static void changeResult1()
{
result = 1;
}
static void changeResult2()
{
result = 2;
}
static void changeResult3()
{
result = 3;
}
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(changeResult1));
Thread t2 = new Thread(new ThreadStart(changeResult2));
Thread t3 = new Thread(new ThreadStart(changeResult3));
t1.Start();
t2.Start();
t3.Start();
Console.WriteLine(result);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我很确定这段代码是不同步的,这意味着result每次执行代码(0,1,2,3)都应该不同.从我的观点来看,结果甚至可以是0,如果主线程在任何一个线程甚至开始之前完成.
但是我2在屏幕上反复得到结果.
为什么?
此代码是否正确同步?
没有.
意味着每次执行代码(0,1,2,3)时结果应该不同.
为什么这是真的?您没有为此声明提供任何理由.
代码错误地同步,这意味着有许多可能的结果.你正在采取一个事实 - 缺乏正确的同步意味着我不知道将会发生什么 - 并从中推断出一个完全不支持的结论 - 每次执行时的观察都会有所不同.从"我不知道会发生什么"中得出的正确推论是,你不知道任何执行会发生什么 ; 特别是你不知道大量运行的行为会有任何特定的分布.
为什么?
为什么?你注意到2是可能的结果,你得到了一个可能的结果.你做两次同样的事情,结果相同; 这并不奇怪.仅仅因为允许运行时产生许多不同的结果并不意味着它必须产生许多不同的结果.两次做同样的事情通常会产生非常相似的结果.
在我看来,观察到的结果是非常合理的.
启动线程是一项昂贵的操作.我希望每个线程的启动时间大大超过实际运行分配给每个线程的代码所花费的时间.
因此,一旦设置了线程1,主线程就会在线程1执行时继续设置线程2.线程1在线程2准备好运行之前很久就完成了.
与线程2和线程3相同.
因此,一旦设置了第三个线程,线程2就已经完成了,并且主线程立即移动到了Console.WriteLine(result);.这是在线程3实际开始之前,并且在线程2完成之后是很长很长很长时间.
所以,当然,结果几乎总是如此2.
为了支持我不科学的分析,我想我可能会添加一些计时代码,看看我是否正确.
void Main()
{
times[0] = sw.Elapsed.TotalMilliseconds;
Thread t1 = new Thread(new ThreadStart(changeResult1));
times[1] = sw.Elapsed.TotalMilliseconds;
Thread t2 = new Thread(new ThreadStart(changeResult2));
times[2] = sw.Elapsed.TotalMilliseconds;
Thread t3 = new Thread(new ThreadStart(changeResult3));
times[3] = sw.Elapsed.TotalMilliseconds;
t1.Start();
times[4] = sw.Elapsed.TotalMilliseconds;
t2.Start();
times[5] = sw.Elapsed.TotalMilliseconds;
t3.Start();
times[6] = sw.Elapsed.TotalMilliseconds;
var r = result.ToString();
times[7] = sw.Elapsed.TotalMilliseconds;
Console.WriteLine(result);
times[8] = sw.Elapsed.TotalMilliseconds;
Thread.Sleep(1000);
times
.Select((x, n) => new { t = (x - times[0]).ToString("0.000"), n})
.OrderBy(x => x.t)
.Dump();
}
static Stopwatch sw = Stopwatch.StartNew();
static double[] times = new double[15];
static int result = 0;
static void changeResult1()
{
times[9] = sw.Elapsed.TotalMilliseconds;
result = 1;
times[10] = sw.Elapsed.TotalMilliseconds;
}
static void changeResult2()
{
times[11] = sw.Elapsed.TotalMilliseconds;
result = 2;
times[12] = sw.Elapsed.TotalMilliseconds;
}
static void changeResult3()
{
times[13] = sw.Elapsed.TotalMilliseconds;
result = 3;
times[14] = sw.Elapsed.TotalMilliseconds;
}
Run Code Online (Sandbox Code Playgroud)
你必须稍微关注弹跳球,但是这样的代码运行产生了这个输出:
这很清楚地表明后面执行的代码t3.Start();是var r = result.ToString();而不是result = 3;.更重要的result = 2;是,在线程3开始之前已经发生了很长时间.