带锁的c#线程

本文关键字:线程 | 更新日期: 2023-09-27 18:17:26

我想我在这里遗漏了一些基础知识,无法找出问题所在。

下面程序的输出不符合预期。有谁能帮我理解一下这个问题吗?

using System;
using System.Threading;
public class Program
{
    private static readonly object _lock = new object();
    public static void Main()
    {
        for (var i = 0; i < 10; i++)
        {
            //Console.WriteLine("Start "+i); 
            System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
            thread.IsBackground = true;
            thread.Start();
        }
    }
    private static void ExecuteInBackground(Object obj)
    {
        lock (_lock)
        {
            Console.WriteLine("A "+obj);
            test.ttt(obj);
        }
    }
}

public static class test
{
    public static void ttt(object obj)
    {
        Console.WriteLine("B "+ obj);
    }
}

我期望在输出中看到0到9 ..但实际输出如下…

A 1
B 1
A 1
B 1
A 3
B 3
A 4
B 4
A 5
B 5
A 6
B 6
A 7
B 7
A 8
B 8
A 9
B 9
A 10
B 10

感谢您的帮助。

请随意使用https://dotnetfiddle.net/nYfbMU

中的代码

谢谢,Reddy .

带锁的c#线程

修改如下:

for (var i = 0; i < 10; i++)
{
    //Console.WriteLine("Start "+i); 
    System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));

:

for (var i = 0; i < 10; i++)
{
    var temp = i;
    //Console.WriteLine("Start "+i); 
    System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(temp));

这是闭包问题。参见为什么在lambda表达式中使用迭代变量是不好的

原始代码不工作的原因如你所期望的,以及为什么临时变量,是因为() => ExecuteInBackground(i)就像说"在未来的某个时候,我希望这个新线程调用ExecuteInBackground方法,在调用时传递任何值I "。由于循环变量在循环开始时进入作用域,在循环结束后退出作用域,因此i的值在调用Thread和执行ExecuteInBackground之间发生变化。通过在循环中使用一个临时变量,它在循环的每次迭代中都超出了作用域,每个线程对ExecuteInBackground的调用实际上是在每次调用中获得一个具有不变值的不同变量,并且i的下一次递增不会把事情搞砸。

这对我很有用。

using System;
using System.Threading;
public class Program
{
    private static readonly object _lock = new object();
    public static void Main()
    {
        for (var i = 0; i <= 10; i++)
        {
            fn(i);
        }
        Console.ReadLine();
    }
    private static void fn(int i)
    {
        System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
        thread.IsBackground = true;
        thread.Start();
    }
    private static void ExecuteInBackground(Object obj)
    {
        lock (_lock)
        {
            Thread.Sleep(500);
            Console.WriteLine("A "+obj);
            test.ttt(obj);
        }
    }
}
public static class test
{
    //private static readonly object _lock = new object();
    public static void ttt(object obj)
    {
        //lock(_lock)
            Console.WriteLine("B "+ obj);
    }
}