Object obj1 = new Object();
Object obj2 = new Object();
这两个都要在前面加上"static"关键词,具体原因我找了些资料,附上一个类似的实例及分析,希望共同提高:
死锁的必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
obj1和obj2是模仿2个资源,这个只要是个静态共享对象都可以
一个线程通过synchronized 锁定自己的资源obj1,
并且需要在后面的过程争取第二个资源obj2,
而第二个线程同理锁定自己的obj2,
然后在后面过程争取第一个资源
因为不剥夺条件,不释放自己,又形成循环争取对方资源的环,
从而形成死锁,不加静态修饰时,主函数执行后,遇到建立对象的代码,就会
创建多个锁对象的副本,所以程序在执行时不会锁上,网上找了个类似例子,你看看:
package com.jk.deadLock;
public class DeadLock implements Runnable{
static Object obj1 = new Object();
static Object obj2 = new Object();
int flag = 1;
public void run(){
System.out.println(flag);
if(flag == 1)
{
synchronized(obj1){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(obj2)
{
System.out.println("my name is t1");
}
}
}
if(flag == 2)
{
synchronized(obj2){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(obj1)
{
System.out.println("my name is t2");
}
}
}
}
public static void main(String[] args) {
DeadLock d1 = new DeadLock();
DeadLock d2 = new DeadLock();
d1.flag = 1;
d2.flag = 2;
Thread t1 = new Thread(d1);
Thread t2 = new Thread(d2);
t1.start();
t2.start();
}
这里如果不为static,当然就创建了多个副本啊。
因为如果不为static,当执行完以下两行时:
DeadLock d1 = new DeadLock();
DeadLock d2 = new DeadLock();
内存里会有d1、d2两个DeadLock对象,每个DeadLock对象中会有obj1、obj2两个Object,这点很重要!即内存中对象如下:
d1:{obj1,obj2,flag}
d2:{obj1,obj2,flag}
设置完flag以后,变成:
d1:{obj1,obj2,flag==1}
d2:{obj1,obj2,flag==2}
现在,进行t1.start()的时候,会相继锁d1.obj1,再锁d1.obj2最后System.out.println("my name is t1");进行t2.start()的时候,会相继锁t2.obj1,再锁t2.obj2最后System.out.println("my name is t2")。所以完全不会存在死锁的问题。
而当两个Object为static 时,内存对象将会是
d1:{flag==1}
d2:{flag==2}
{obj1,obj2}
此时,再运行 t1.start(); t2.start();时,obj1和obj2会分别被两个d锁住,从而引发死锁。
|