C#线程的死锁问题

2025-04-26 16:15:05
推荐回答(4个)
回答1:

//我怀疑是由于你们测试的时候,代码运行的太快了,所以才不会锁住的
//所以我建议你在i--上加入一个线程睡眠操作
//以下是我的测试代码
//--------------
//更新
//将睡眠时间减少为100,事实上是有锁的效果,但不会死锁住的。神奇了。
class Program
{
    private readonly object _locker = new object();
    static void Main(string[] args)
    {
        Console.WriteLine("测试开始");
        //三种测试方式
        //每次测试一种
        TestWithTestInputInt();
        //TestWithTestInputObject();
        //TestWithLockTestWithOuterObject();
        //如果没有看到打印出“测试结束”或者其它信息,表示锁住了
        Console.WriteLine("测试结束");
        Console.Read();
    }
    /// 
    /// 锁住自身,测试输入值参数
    /// 

    public static void TestWithTestInputInt()
    {
        //测试方式0-1 -可锁
        //new Thread(() => new Program().TestInputInt(21)).Start();
        //new Thread(() => new Program().TestInputInt(22)).Start();
        //new Thread(() => new Program().TestInputInt(23)).Start();
        //new Program().TestInputInt(24);
 
        //测试方式0-2 -可锁
        new Program().TestInputInt(21);
        new Program().TestInputInt(22);
        new Program().TestInputInt(23);
    }
    /// 
    /// 锁住自身,测试输入object参数 -结果 锁住
    /// 

    public static void TestWithTestInputObject()
    {
        //测试方式2-1 -可锁
        //new Thread(() => new Program().TestInputObject(21)).Start();
        //new Thread(() => new Program().TestInputObject(22)).Start();
        //new Thread(() => new Program().TestInputObject(23)).Start();
        //new Program().TestInputObject(24);
 
        //测试方式2-2 -可锁
        //new Program().TestInputObject(21);
        //new Program().TestInputObject(22);
        //new Program().TestInputObject(23);
    }
    /// 
    /// 锁住自身,测试锁住外部object -结果 锁住
    /// 

    public static void TestWithLockTestWithOuterObject()
    {
        //测试方式1-1 -可锁
        //new Thread(() => new Program().LockTestWithOuterObject(21)).Start();
        //new Thread(() => new Program().LockTestWithOuterObject(22)).Start();
        //new Thread(() => new Program().LockTestWithOuterObject(23)).Start();
        //new Program().LockTestWithOuterObject(24);
 
        //测试方式1-2 -可锁
        //new Program().LockTestWithOuterObject(21);
        //new Program().LockTestWithOuterObject(22);
        //new Program().LockTestWithOuterObject(23);
    }
    public void LockTestWithOuterObject(int msg)
    {
        lock (_locker)
        {
            Thread.Sleep(100);
        }
        Console.WriteLine(msg);
    }
    public void TestInputObject(object i)
    {
        lock (this)
        {
            int num = (int)i;
            if (num > 10)
            {
                Thread.Sleep(100);
                num--;
                TestInputObject(num);
            }
        }
        Console.WriteLine(i);
    }
 
    public void TestInputInt(int num)
    {
        lock (this)
        {
            if (num > 10)
            {
                Thread.Sleep(100);
                num--;
                TestInputInt(num);
            }
        }
        Console.WriteLine(num);
    }
}

回答2:

不会发生死锁,因为你每次传递的是一个值,可以说是不同的地址。所以每次锁定的地址都不一样,不会发生死锁现象!
如果参数是个引用类型的话就会发生死锁,这个是值类型不会发生死锁!

回答3:

不会发生死锁。您可以试试如下的语句
using System;

namespace Test
{
class Test
{
static void Main()
{
object lockObj = new object();
lock (lockObj)
{
lock (lockObj)
{
Console.WriteLine("Hello, world");
}
}
}
}
}
您会发现这个程序可以正确的输出 hello,world.
原因我想应该是Lock语句对 “同一个线程多次锁同一个对象不予理会"。所以,您的递归函数中第一次的lock语句会保证不会有多个线程同时执行test函数,而在test函数内部调用lock时会不予理会。
但是提醒您一下,http://msdn.microsoft.com/zh-cn/library/c5kehkcz(VS.80).aspx
msdn中明确的说明lock (this)是个不好的习惯。

回答4:

会,因为第一次调用test()函数时,就已经把this锁定了,如果i的值大于10的话就会递归调用test()函数,此时会再次对this加锁,但是this在上一层调用时已经锁定了,所以就会一直阻塞在加锁的地方等待上一层调用释放this,然而,第二层的递归调用因为阻塞不能运行到函数返回的地方,就导致第一层的程序运行不出lock块,即,第一层的程序始终不能将this解除锁定.就造成第一层调用test()函数和第二层调用的test()函数对this临界资源的无限等待导致死锁.