我正在尝试仅使用 MethodImplOptions.Synchronized 方法表示法重现一些死锁:
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
namespace Lab_01
{
class Program1
{
[MethodImpl(MethodImplOptions.Synchronized)]
static void Resource1(int starterIndex, bool startNext = true)
{
Console.WriteLine("Resource1 is used ({0})", starterIndex);
Thread.Sleep(1000);
if (startNext)
{
Resource2(starterIndex, false);
}
Console.WriteLine("Resource1 is free ({0})", starterIndex);
}
[MethodImpl(MethodImplOptions.Synchronized)]
static void Resource2(int starterIndex, bool startNext = true)
{
Console.WriteLine("Resource2 is used ({0})", starterIndex);
Thread.Sleep(1000);
if (startNext)
{
Resource1(starterIndex, false);
}
Console.WriteLine("Resource2 is free ({0})", starterIndex);
}
static void Main(string[] args)
{
Locker locker1 = new Locker();
Locker locker2 = new Locker();
new Thread(delegate()
{
Resource1(0);
}).Start();
new Thread(delegate()
{
Resource2(1);
}).Start();
}
}
}
我期望的是
- 第一个线程启动,只有 Resource1 方法被锁定,它等待 1 秒
- 当第一个线程处于休眠状态时(这 1 秒),第二个线程启动并锁定了第二个资源(Resource2)。它休眠 1 秒。
- 首先结束睡眠的线程,比如第一个线程,想要锁定第二个资源,但它不能因为它已经被锁定,并且不能被释放,因为第二个线程处于相同的情况(它想要锁定 Recource1,但它已被锁定)。一言以蔽之,常规的死锁情况。
但是当我启动它时,它不会自行锁定,我得到这个输出:
C:\Users\ginz\C#\19-\Lab_01\Lab_01\bin\Debug>Lab_01.exe
Resource1 is used (0)
Resource2 is used (0)
Resource2 is free (0)
Resource1 is free (0)
Resource2 is used (1)
Resource1 is used (1)
Resource1 is free (1)
Resource2 is free (1)
所以,第二个线程只有在第一个线程结束时才启动,但我认为它应该更早开始。为什么是这样?
我知道可以通过使用lock
关键字简单地复制这种行为,但在我的情况下,这是不合适的方式:
Object obj1 = new Object(), obj2 = new Object();
new Thread(new ThreadStart(delegate()
{
lock (obj1)
{
Thread.Sleep(1000);
lock (obj2)
{
Thread.Sleep(500);
}
}
})).Start();
new Thread(new ThreadStart(delegate()
{
lock (obj2)
{
Thread.Sleep(1000);
lock (obj1)
{
Thread.Sleep(500);
}
}
})).Start();
你能在这种情况下帮助我吗?
提前致谢, 德米特里