线程死锁

每个对象都有一把唯一的锁,这个锁只是针对此对象定义的所有synchonized方法以及synchonized(this)代码块。一个线程进入了synchonized方法或者synchonized(this)代码块就相当于得到了此对象的锁,此时另外一个县城就无法进入此对象的其它synchonized方法或者synchonized(this)。直到把锁释放。

每个类对应一把唯一的锁,这个锁和对象锁是两个不同的锁,它只针对此类定义的所有synchonized静态方法以及synchonized(Object.class)代码块。一个线程进入了synchonized static方法或者synchonized(Object.class)代码块就相当于得到了此对象的静态锁,此时另外一个线程就无法进入此类的其它synchonized static 方法或者synchonized(Object.class)。直到把静态锁释放。

对象锁和静态锁是两个完全不同的锁,他们之间互不影响。

以下代码能够表现线程的死锁。
当线程a执行addLa()方法时,得到对象la的锁,睡眠10秒,此时线程b执行addLb()方法,得到对象lb的锁,两个线程睡眠结束后,la()执行lb.add()方法,由于lb是一个线程安全的容器vector,它的add()方法为synchonized,需要得到lb的对象锁,而此时线程b已经得到了lb的对象锁,还没有释放,所以线程a只有进入阻塞状态。而线程b睡眠结束后需要调用la.add(),它同样需要得到la的对象锁,而la的对象锁被线程a占有,这样两个线程便都无法继续执行,进入死锁状态。

如果我们把la和lb由Vector变为ArrayList,这两个线程都能继续执行,而不发生死锁,这是为什么呢?这是因为ArrayList是一个非线程安全的容器,当两个线程睡眠10秒结束后,线程a执行lb.add()方法,此时因为add()并非synchnoized,所以不需要得到它的锁同样可以继续执行此方法。线程b同样如此。因此不会构成死锁。

package com.test; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.List; 
import java.util.Vector; 

import javax.swing.event.ListSelectionEvent; 

import com.google.common.collect.Lists; 

public class A { 
public static void main(String args[]){ 
Thread a = new Thread(new Ta("thread a")); 
Thread b = new Thread(new Tb("thread b")); 
a.start(); 
b.start(); 
} 
} 

class Ta implements Runnable{ 
static Ca a = new Ca(); 
String name; 
public Ta(String name){ 
this.name = name; 
} 
@Override 
public void run() { 
// TODO Auto-generated method stub 
while(true){ 
System.out.println(name); 
a.addLa(0); 
} 
} 

} 

class Tb implements Runnable{ 
String name; 
public Tb(String name){ 
this.name = name; 
} 
public void run() { 
while(true){ 
System.out.println(name); 
Ta.a.addLb(0); 
} 
} 
} 


class Ca{ 
Vector<Integer> la = new Vector<Integer>(); 
Vector<Integer> lb = new Vector<Integer>(); 
// List<Integer> la = new ArrayList<Integer>(); 
// List<Integer> lb = new ArrayList<Integer>(); 
public void addLa(int n){ 
synchronized (la) { 
la.add(n); 
try{ 
Thread.sleep(10000); //睡眠10秒,此时调用此方法的线程已经得等到了对象la的对象锁。 
}catch(Exception e){ 
e.printStatckTrace(); 
} 
lb.add(n); 
} 
} 
public void addLb(int n){ 
synchronized (lb) { 
lb.add(n); 
try{ 
Thread.sleep(10000); //睡眠10秒,此时调用此方法的线程已经得等到了对象lb的对象锁。 
}catch(Exception e){ 
e.printStatckTrace(); 
} 
la.add(n); 
} 
} 
}

 

 

你可能感兴趣的:(thread 死锁)