我一直在学习多线程编程并致力于解决哲学家就餐问题。我试图在不休眠任何线程的情况下造成死锁。这是我正在使用的代码片段:
public class Program
{
const int NumberOfPhilosophers = 5;
const int NumberOfForks = 5;
const int EatingTimeInMs = 20;
static object[] forks = new object[NumberOfForks];
static Thread[] philosopherEatingThreads = new Thread[NumberOfPhilosophers];
public static void Main(string[] args)
{
for (int i = 0; i < NumberOfForks; i++)
{
forks[i] = new object();
}
for (int i = 0; i < NumberOfPhilosophers; i++)
{
int philosopherIndex = i;
philosopherEatingThreads[i] = new Thread(() => { DoWork(philosopherIndex); })
{
Name = philosopherIndex.ToString()
};
philosopherEatingThreads[philosopherIndex].Start();
}
}
public static void DoWork(int philosopherIndex)
{
int fork1Index = philosopherIndex;
int fork2Index = (philosopherIndex + 1 ) % NumberOfForks;
var fork1 = forks[fork1Index];
var fork2 = forks[fork2Index];
lock (fork1)
{
lock (fork2)
{
Thread.Sleep(EatingTimeInMs);
}
}
}
}
在尝试了几次之后,我没有看到任何死锁。我知道没有遇到死锁并不意味着这段代码是线程安全的。例如,当我更改锁定语句并添加延迟时,我会导致死锁。
lock (fork1)
{
Thread.Sleep(10);
lock (fork2)
{
Thread.Sleep(EatingTimeInMs);
}
}
我有两个问题:
- 一个接一个地使用两个锁语句是原子操作吗?
- 如果使用 Thread.Sleep() 导致代码片段死锁,这是否意味着代码片段不是线程安全的?
谢谢!