同步特性使用起来非常方便,功能很强大。但有的时候考虑不周的话有可能出现线程死锁。死锁主要是多个线程争抢资源造成的。
下面通过一个例子演示死锁:
class Resource
{
private int res = 0;
public int getRes()
{
return res;
}
public void setRes(int res)
{
this.res = res;
}
}
class DeadLock1 extends Thread
{
Resource res1 = null;
Resource res2 = null;
public DeadLock1(String name, Resource res1, Resource res2)
{
super(name);
this.res1 = res1;
this.res2 = res2;
}
@Override
public void run()
{
// 获取res1的锁从而锁住res1
synchronized (res1)
{
for (int i = 0; i < 10; i++)
{
int r = res1.getRes();
r++;
res1.setRes(r);
}
System.out.println(getName() + ":资源1处理完毕等待资源2...");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
System.out.println(getName() + "异常中断");
}
// 此时res1并未释放
// 获取res2的锁从而锁住res2
synchronized (res2)
{
for (int i = 0; i < 10; i++)
{
int r = res2.getRes();
r++;
res2.setRes(r);
}
System.out.println(getName() + ":资源2处理完毕...");
}
}
}
}
class DeadLock2 extends Thread
{
Resource res1 = null;
Resource res2 = null;
public DeadLock2(String name, Resource res1, Resource res2)
{
super(name);
this.res1 = res1;
this.res2 = res2;
}
@Override
public void run()
{
// 获取res1的锁从而锁住res2
synchronized (res2)
{
for (int i = 0; i < 10; i++)
{
int r = res2.getRes();
r++;
res2.setRes(r);
}
System.out.println(getName() + ":资源2处理完毕等待资源1...");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
System.out.println(getName() + "异常中断");
}
// 此时res2并未释放
// 获取res1的锁从而锁住res1
synchronized (res1)
{
for (int i = 0; i < 10; i++)
{
int r = res1.getRes();
r++;
res1.setRes(r);
}
System.out.println(getName() + ":资源1处理完毕...");
}
}
}
}
public class DeadLockDemo
{
public static void main(String[] args)
{
// 新建共享资源
Resource res1 = new Resource();
Resource res2 = new Resource();
DeadLock1 lock1 = new DeadLock1("线程1", res1, res2);
DeadLock2 lock2 = new DeadLock2("线程2", res1, res2);
lock1.start();
lock2.start();
}
}
运行结果:
线程1:资源1处理完毕等待资源2…
线程2:资源2处理完毕等待资源1…
程序说明:线程1和线程2共享资源res1和res2,当线程1首先运行获取资源res1的锁从而锁住res1,调用sleep()使线程2得以运行,此时资源res1还未释放。线程2锁住资源res2,调用sleep(),线程1运行,此时资源res2还未释放,线程1尝试获取资源res2但是已经被线程2锁住,线程2睡眠过后开始运行尝试获取资源res1的锁但是已经被线程1锁住。此时线程1和线程2处于死锁状态。