1.yes
2.
0线程试图给A加锁
0线程成功给A加锁
0线程试图给B加锁
0线程成功给B加锁
》释放对B的锁
》释放对A的锁,此时A,B都是自由的
1线程试图给B加锁
1线程成功给B加锁
1线程试图给A加锁
1线程成功给A加锁
0线程试图给A加锁
》1线程释放A的锁
》1线程释放B的锁,此时A,B又再次成为自由的
1线程试图给B加锁
0线程成功给A加锁,A被封锁<--
0线程试图给B加锁 |
1线程成功给B加锁,B被封锁<--+-------------------------------------|
1线程试图给A加锁,由于A被线程0锁定,且线程0又在等待B,但是B却被线程1锁定了,所以进入死锁状态。
2.
0线程试图给A加锁
0线程成功给A加锁
0线程试图给B加锁
0线程成功给B加锁
》释放对B的锁
》释放对A的锁,此时A,B都是自由的
1线程试图给B加锁
1线程成功给B加锁
1线程试图给A加锁
1线程成功给A加锁
0线程试图给A加锁
》1线程释放A的锁
》1线程释放B的锁,此时A,B又再次成为自由的
1线程试图给B加锁
0线程成功给A加锁,A被封锁<--
0线程试图给B加锁 |
1线程成功给B加锁,B被封锁<--+-------------------------------------|
1线程试图给A加锁,由于A被线程0锁定,且线程0又在等待B,但是B却被线程1锁定了,所以进入死锁状态。
public static void sleep(long millis)
throws InterruptedException Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds. THE THREAD DOES NOT LOSE OWNERSHIP OF ANY MONITORS.u can research this by adding print statement before and after sleep(),and set longer time for sleep().and the answer to the last question u said should be same, actually, I think the difference between sleep() and wait() exists just the thread paused by sleep() will wakeup only by timeout, but the one pasued by wait() can be either timeout or notify()so the regular way is putting sleep() out of synchronized statement.
结合你的这句话THE THREAD DOES NOT LOSE OWNERSHIP OF ANY MONITORS.,也就是说线程在这整个过程中,始终控制着那个对象的锁喽?是不是这样理解的啊?
Notice that when
the thread has finished sleeping, IT DOES NOT CONTINUE EXECUTING. As you
would expect, it enters the Ready state and will only execute when the thread
scheduler allows it to do so. For this reason, you should expect that a
sleep() call will block a thread for at least the requested time, but it might
block for much longer. This suggests that very careful thought should be
given to your design before you expect any meaning from the nanosecond
accuracy version of the sleep() method.
Thread-0 Looking for lock on Resource A
Thread-0 Obtained lock on Resource A
Thread-0 Looking for lock on Resource B
Thread-0 Obtained lock on Resource B
Thread-1 Looking for lock on Resource B
Thread-1 Obtained lock on Resource B
Thread-1 Looking for lock on Resource A
Thread-1 Obtained lock on Resource A
之后会出现
Thread-0 Looking for lock on Resource A
Thread-1 Looking for lock on Resource B
Thread-0 Obtained lock on Resource A
Thread-0 Looking for lock on Resource B
Thread-1 Obtained lock on Resource B
Thread-1 Looking for lock on Resource A
(死锁中......)
这样啊?
既然sleep(),退出了Running状态,也一定是释放了锁了啊,为什么最后会死锁呢?请教请教请教
这样你理解了吗?
但是我在写这个程序的输出结果的时候,还是没有搞清楚,你来看看我写的output
注:线程0和1 资源对象A和B >>:寻找 ++:获得 --:释放
输出结果:
0>>A
0++A
0>>B
0++B
0.sleep(100); //在sleep期间,线程0让出执行权,但是不释放B和A.那么线程0在sleep期间,线程1是在干什么呢?是下面这样吗?
1>>B //这个时候B实际上没有进入运行状态啊,而是处在Seeking Lock State,等到线程0继续执行完,线程0Dead,释放了B和A,那么
1++B
1>>A
1++A
1.sleep(100)这么理解的话,变成了o和1轮流来,就不会发生死锁了啊。请问我哪里理解错误了?
{
public static void main(String[] args)
{
Object a = "Resource A";
Object b = "Resource B";
Thread t1 = new Thread(new Deadlock(a, b));
Thread t2 = new Thread(new Deadlock(b, a));
t1.start();
t2.start();
} private Object firstResource;
private Object secondResource; public Deadlock(Object first, Object second)
{
firstResource = first;
secondResource = second;
} public void run()
{
for (;;)
{
System.out.println(Thread.currentThread().getName()+" Looking for lock on "+firstResource); synchronized (firstResource)
{
System.out.println(Thread.currentThread().getName()+" Obtained lock on "+firstResource);
try
{
Thread.sleep(1000);
}
catch (InterruptedException ex) {}
System.out.println(Thread.currentThread().getName()+" Looking for lock on " + secondResource);
synchronized (secondResource)
{
System.out.println(Thread.currentThread().getName()+" Obtained lock on "+secondResource);
// simulate some time consuming activity
}
}
}
}
}
t1申请到a锁等待b锁的同时
t2申请到b锁等待a锁的时产生的
我在申请锁的间隔中加入sleep,使得另一线程取得另外的资源,造成很容易死锁。
而原先也需要同样的条件,只不过因为在两处申请资源中间被中断不那么容易
public class Deadlock implements Runnable
{
public static void main(String[] args)
{
Object a = "Resource A";
Object b = "Resource B";
Thread t1 = new Thread(new Deadlock(a, b));
Thread t2 = new Thread(new Deadlock(b, a));
t1.start();
t2.start();
} private Object firstResource;
private Object secondResource; public Deadlock(Object first, Object second)
{
firstResource = first;
secondResource = second;
} public void run()
{
for (;;)
{
System.out.println(Thread.currentThread().getName()+" Looking for lock on "+firstResource); synchronized (firstResource)
{
System.out.println(Thread.currentThread().getName()+" Obtained lock on "+firstResource);
System.out.println(Thread.currentThread().getName()+" Looking for lock on " + secondResource);
try
{
Thread.sleep(1000);
}
catch (InterruptedException ex) {}
synchronized (secondResource)
{
System.out.println(Thread.currentThread().getName()+" Obtained lock on "+secondResource);
// simulate some time consuming activity
}
}
}
}
}
zych72(闹闹)说得对。线程何时被运行是一个不确定的事,依赖与实现者,所以我们写程序时应该深入理解线程模型才能写出线程安全的代码来。