Java对多线程的支持(二) - 线程死锁 (一)

2014-11-24 11:44:59 · 作者: · 浏览: 34

我们知道,当线程A由于某种原因(如等待IO操作完成、调用了sleep函数等)放弃了执行权时,操作系统就会调度另一个处于就绪状态(Runnable) 的线程B来执行。只有当线程A所等待的事件发生(如IO操作完成,睡眠时间结束)后,线程A才会被设置成就绪状态,等待操作系统的调度。

然而有时候可能会出现这样一种情况:线程A为了等待线程B而处于阻塞状态(blocked),此时线程B恰好又在等待线程A而处于阻塞状态。这时A,B都在相互等待对方,因而A,B谁都不能得到执行机会。这种由于线程的相互等待而导致这些线程都无法执行的现象,就叫做线程死锁。


下面我们手动造成线程死锁,来体会下死锁的概念。

先要说明一点的是,在Java中,synchronized关键字也可以用来声明一个方法,如public synchronized run()。一个同步的方法是通过请求this对象的监视器来实现同步的,这是理解以下程序的前提。

我们首先定义一个实现了Runnable接口的类ThreadLock,然后定义一个同步的方法fun(),并在该方法内部定义了一个请求Object对象的同步块;

在run()方法中定义一个请求Object对象的同步块,接着在后面再定义一个请求this对象的同步块;

描述起来比较抽象,还是直接上代码吧。。

[java]
package cls;

public class ThreadLockDemo
{

/**
* @param args
*/
public static void main(String[] args)
{
ThreadLock tl = new ThreadLock();

new Thread(tl).start();
new Thread(tl).start();
}
}

class ThreadLock implements Runnable
{
private Object obj = new Object(); // Synchronized Object
boolean bool = false; //

// Synchronized method run()
public void run()
{
if(bool == true)
{
fun();
}
else
{
synchronized (obj)
{
bool = true;
// Sleep for a while, give up running.
try
{
Thread.sleep(50);
}
catch(Exception e)
{
e.printStackTrace();
}

// Enter the synchronized block, using this Object.
synchronized(this)
{
System.out.println(Thread.currentThread().getName() + " is running !");
}
}
}
}
// Synchronized method fun()
public synchronized void fun()
{
synchronized(obj)
{
while(true)
{
System.out.println(Thread.currentThread().getName() + " is running !");
}
}
}
}

package cls;

public class ThreadLockDemo
{

/**
* @param args
*/
public static void main(String[] args)
{
ThreadLock tl = new ThreadLock();

new Thread(tl).start();
new Thread(tl).start();
}
}

class ThreadLock implements Runnable
{
private Object obj = new Object(); // Synchronized Object
boolean bool = false; //

// Synchronized method run()
public void run()
{
if(bool == true)
{
fun();
}
else
{
synchronized (obj)
{
bool = true;
// Sleep for a while, give up running.
try
{
Thread.sleep(50);
}
catch(Exception e)
{
e.printStackTrace();
}

// Enter the synchronized block, using this Object.
synchronized(this)
{
System.out.println(Thread.currentThread().getName() + " is running !");
}
}
}
}
// Synchronized method fun()
public synchronized void fun()
{
synchronized(obj)
{
while(true)
{
System.out.println(Thread.currentThread().getName() + " is running !");
}
}
}
}

执行这个程序时,我们发现没有任何输出结果,而此时程序也并没有退出。这时候程序中的两个线程都因为等待对方而得不到执行的机会,发生了死锁。

我们来分析一下这个程序发生死锁现象的过程:

首先,线程A启动,bool的值为false,执行 run()方法中的else分支,给obj对象加锁,然后将bool改成true,再睡眠。此时A就已经放弃了执行权。

这时线程B启动,bool的值为 true,则执行run()方法中的第一个分支,调用fun()方法。因为fu