c#锁未按预期工作

c#锁未按预期工作,c#,.net,multithreading,locking,interlocked,C#,.net,Multithreading,Locking,Interlocked,此类使用锁和互锁 两者都增加count.with_lock.Run()和使用联锁运行()增加计数在96-100之间打印 我希望他们两个都打印100。我犯了什么错误 public static class increaseCount { public static int counter = 0; public static readonly object myLock = new object(); public static class with_lock {

此类使用
互锁

两者都
增加count.with_lock.Run()
使用联锁运行()增加计数在96-100之间打印

我希望他们两个都打印100。我犯了什么错误

public static class increaseCount {
    public static int counter = 0;
    public static readonly object myLock = new object();
    public static class with_lock {
        public static void Run() {
            List<Thread> pool = new List<Thread>();
            for(int i = 0; i < 100; i++) {
                pool.Add(new Thread(f));
            }
            Parallel.ForEach(pool, x => x.Start());
            Console.WriteLine(counter); //should print 100
        }

        static void f() {
            lock(myLock) {
                counter++;
            }
        }
    }

    public static class with_interlock {
        public static void Run() {
            List<Thread> pool = new List<Thread>();
            for(int i = 0; i < 100; i++) {
                pool.Add(new Thread(f));
            }
            Parallel.ForEach(pool, x => x.Start());
            Console.WriteLine(counter);//should print 100
        }

        static void f() {
            Interlocked.Add(ref counter, 1);
        }
    }
}
公共静态类递增计数{
公共静态整数计数器=0;
公共静态只读对象myLock=new object();
带有_锁的公共静态类{
公共静态无效运行(){
列表池=新列表();
对于(int i=0;i<100;i++){
添加(新线程(f));
}
Parallel.ForEach(pool,x=>x.Start());
Console.WriteLine(计数器);//应打印100
}
静态空隙f(){
锁(myLock){
计数器++;
}
}
}
带有\u联锁的公共静态类{
公共静态无效运行(){
列表池=新列表();
对于(int i=0;i<100;i++){
添加(新线程(f));
}
Parallel.ForEach(pool,x=>x.Start());
Console.WriteLine(计数器);//应打印100
}
静态空隙f(){
联锁。添加(参考计数器,1);
}
}
}

在这两种情况下,您都会启动线程,但不会等待线程完成,因此在打印结果和应用程序关闭之前,您不会达到100

如果在启动所有线程后,您将等待所有这些线程完成
thread.Join
,您将始终得到正确的结果:

List<Thread> pool = new List<Thread>();
for (int i = 0; i < 100; i++)
{
    pool.Add(new Thread(f));
}

Parallel.ForEach(pool, x => x.Start());
foreach (var thread in pool)
{
    thread.Join();
}

Console.WriteLine(counter);
列表池=新列表();
对于(int i=0;i<100;i++)
{
添加(新线程(f));
}
Parallel.ForEach(pool,x=>x.Start());
foreach(池中的var线程)
{
thread.Join();
}
控制台。写线(计数器);

注意:这看起来像是某种测试,但你应该知道,在一个
锁上阻塞多个线程是一种巨大的资源浪费。

在这两种情况下,你都启动了线程,但你不会等待它们完成,所以在打印结果和关闭应用之前,你不会达到100

如果在启动所有线程后,您将等待所有这些线程完成
thread.Join
,您将始终得到正确的结果:

List<Thread> pool = new List<Thread>();
for (int i = 0; i < 100; i++)
{
    pool.Add(new Thread(f));
}

Parallel.ForEach(pool, x => x.Start());
foreach (var thread in pool)
{
    thread.Join();
}

Console.WriteLine(counter);
列表池=新列表();
对于(int i=0;i<100;i++)
{
添加(新线程(f));
}
Parallel.ForEach(pool,x=>x.Start());
foreach(池中的var线程)
{
thread.Join();
}
控制台。写线(计数器);

注:这似乎是某种测试,但是你应该知道,在一个
锁上阻塞多个线程是一种巨大的资源浪费。

我相信这是因为你的
并行。Foreach
调用只调用
池中所有线程的start
,但它们不一定在循环完成和
控制台.WriteLine
被称为。如果要插入
线程。Sleep(5000);//在
控制台前5s sleep
或类似功能。WriteLine
可能总是打印出您期望的内容。

我相信这是因为您的
并行。Foreach
调用只是在
池中的所有线程上调用start
但它们不一定在循环完成和
控制台。调用WriteLine
。如果要插入
线程。Sleep(5000);//在
控制台前使用5s sleep
或类似功能。WriteLine
可能会始终打印出您期望的内容。

您的代码很好。唯一的问题是你的期望。基本上,在计数器显示之前,并非所有100个线程都可以运行。试着在控制台前放一根线。睡眠(1000)。写线(计数器),你就会明白我的意思


编辑:第一次作为评论发布错误。

您的代码没有问题。唯一的问题是你的期望。基本上,在计数器显示之前,并非所有100个线程都可以运行。试着在控制台前放一根线。睡眠(1000)。写线(计数器),你就会明白我的意思


编辑:第一次作为评论发布错误。

您的代码没有问题。唯一的问题是你的期望。基本上,在计数器显示之前,并非所有100个线程都可以运行。试着在控制台前放一个线程。Sleep(1000)。WriteLine(counter),你就会明白我的意思。你的代码很好。唯一的问题是你的期望。基本上,在计数器显示之前,并非所有100个线程都可以运行。试着在控制台前放一根线。睡眠(1000)。写线(计数器),你就会明白我的意思。