首先,了解死锁,先简略了解,代码块的锁:synchronized (对象){} 锁住参数对象。 synchronized对象和内容访问单一;
简略扫过一下,死锁和非死锁代码:
死锁:
class Zhangsan{ // 定义张三类
public void say(){
System.out.println("张三对李四说:“你给我画,我就把书给你。”") ;
}
public void get(){
System.out.println("张三得到画了。") ;
}
}
class Lisi{ // 定义李四类
public void say(){
System.out.println("李四对张三说:“你给我书,我就把画给你”") ;
}
public void get(){
System.out.println("李四得到书了。") ;
}
}
public class ThreadDeadLock implements Runnable{
private static Zhangsan zs = new Zhangsan() ; // 实例化static型对象
private static Lisi ls = new Lisi() ; // 实例化static型对象
private boolean flag = false ; // 声明标志位,判断那个先说话
public void run(){ // 覆写run()方法
if(flag){
synchronized(zs){ // 同步张三
zs.say() ;
System.out.println("张三正在等待李四的画...");
try{
Thread.sleep(500) ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
synchronized(ls){
zs.get() ;
}
}
}else{
synchronized(ls){
ls.say() ;
System.out.println("李四正在等待张三的书...");
try{
Thread.sleep(500) ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
synchronized(zs){
ls.get() ;
}
}
}
}
public static void main(String args[]){
ThreadDeadLock t1 = new ThreadDeadLock() ; // 控制张三
ThreadDeadLock t2 = new ThreadDeadLock() ; // 控制李四
t1.flag = true ;
t2.flag = false ;
Thread thA = new Thread(t1) ;
Thread thB = new Thread(t2) ;
thA.start() ;
thB.start() ;
}
}
非死锁:
class Zhangsan1{ // 定义张三类
public void say(){
System.out.println("张三对李四说:“你给我画,我就把书给你。”") ;
}
public void get(){
System.out.println("张三得到画了。") ;
}
}
class Lisi1{ // 定义李四类
public void say(){
System.out.println("李四对张三说:“你给我书,我就把画给你”") ;
}
public void get(){
System.out.println("李四得到书了。") ;
}
}
public class ThreadDeadUnLock implements Runnable{
private static Zhangsan1 zs = new Zhangsan1() ; // 实例化static型对象
private static Lisi1 ls = new Lisi1() ; // 实例化static型对象
private boolean flag = false ; // 声明标志位,判断那个先说话
public void run(){ // 覆写run()方法
if(flag){
synchronized(zs){ // 同步张三
zs.say() ;
System.out.println("张三正在等待李四的画...");
try{
Thread.sleep(500);
zs.wait(); //线程睡眠释放资源
}catch(InterruptedException e){
e.printStackTrace() ;
}
synchronized(ls){
zs.get() ;
}
}
}else{
synchronized(ls){
ls.say() ;
System.out.println("李四正在等待张三的书...");
try{
Thread.sleep(500) ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
synchronized(zs){
ls.get() ;
zs.notify();
}
}
}
}
public static void main(String args[]){
ThreadDeadUnLock t1 = new ThreadDeadUnLock() ; // 控制张三
ThreadDeadUnLock t2 = new ThreadDeadUnLock() ; // 控制李四
t1.flag = true ;
t2.flag = false ;
Thread thA = new Thread(t1) ;
Thread thB = new Thread(t2) ;
thA.start() ;
thB.start() ;
}
}
看完了吗?我相信机智的你一定已经发现了他们那些细小的区别。那么我们来分析一下他们运行的过程,在此要记住一个核心知识:睡眠(sleep)不释放线程资源,wait释放线程资源。
死锁: 创建俩个线程: 线程一synchronized(zs),执行,后面进入睡眠。
在此期间同步锁依旧存在。
线程二synchronized(ls),执行,睡眠
线程一醒来,执行内部锁synchronized(ls),ls对象被占用,等待。。。
线程二醒来,执行内部锁synchronized(zs),zs对象被占用,等待。。。
活锁: 创建俩个线程: 线程一synchronized(zs),执行,后面进入睡眠。wait()释放资源
在此期间synchronized(zs)被解锁.
线程二synchronized(ls),执行,睡眠
线程一未被唤醒
线程二醒来,执行内部锁synchronized(zs),zs对象未被占用,执行代码,notify()唤醒线程一。
线程一执行代码。
机智的你一定懂了。