自旋锁,死锁与重入锁
重入锁
重入锁---- 能够让线程进行重入的锁叫作重入锁
锁重入----让线程进行重入的过程叫作锁的重入
public class demo { public static synchronized void a() { System.out.println("a"); b(); } private static synchronized void b() { System.out.println("b"); } public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { demo.a(); } }).start();; } }
锁是当前类的实例,当进入a方法的时候,线程必须先拿到当前类的实例(锁),这个时候,a的方法内同时调用了b方法,b方法也是用synchronized来修饰的,所以b方法也需要线程获取锁才能让线程进来
进入a方法的时候,线程拿的锁是当前类的实例(锁),当线程要进入b方法的时候,线程拿的锁也是当前类的实例(锁),前一把锁和后一把锁都是同一个把锁,这个时候就发送了锁重入现象
1 public class Demo { 2 3 4 /* 5 * synchronized锁在方法上锁的对象是当前类的实例 6 */ 7 public synchronized void a() { 8 System.out.println("a"); 9 // b(); 10 11 12 try { 13 Thread.sleep(1000); 14 } catch (InterruptedException e) { 15 // TODO Auto-generated catch block 16 e.printStackTrace(); 17 } 18 } 19 20 21 public synchronized void b() { 22 System.out.println("b"); 23 24 try { 25 Thread.sleep(1000); 26 } catch (InterruptedException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 31 } 32 33 34 public static void main(String[] args) { 35 Demo d = new Demo(); 36 37 new Thread(new Runnable() { 38 39 @Override 40 public void run() { 41 d.a(); 42 } 43 }).start(); 44 45 46 new Thread(new Runnable() { 47 48 @Override 49 public void run() { 50 d.b(); 51 } 52 }).start(); 53 } 54 55 } //当调用a时没有调用b
自旋锁
“旋”的是CPU的时间片,空转CPU,当一个 线程拿到对象头的信息到栈帧中,另外的线程再想获取必须不停自旋等待第一个线程方法体执行完毕之后才能自己再去执行。
1 public class Demo2 { 2 3 public static void main(String[] args) { 4 new Thread(new Runnable() { 5 @Override 6 public void run() { 7 System.out.println(Thread.currentThread().getName() + "线程开始执行..."); 8 try { 9 Thread.sleep(new Random().nextInt(2000)); 10 } catch (InterruptedException e) { 11 // TODO Auto-generated catch block 12 e.printStackTrace(); 13 } 14 System.out.println(Thread.currentThread().getName() + "线程执行完毕了..."); 15 } 16 17 }).start(); 18 19 //第二个线程 20 21 new Thread(new Runnable() { 22 @Override 23 public void run() { 24 System.out.println(Thread.currentThread().getName() + "线程开始执行..."); 25 try { 26 Thread.sleep(new Random().nextInt(2000)); 27 } catch (InterruptedException e) { 28 // TODO Auto-generated catch block 29 e.printStackTrace(); 30 } 31 System.out.println(Thread.currentThread().getName() + "线程执行完毕了..."); 32 } 33 34 }).start(); 35 36 //第三个线程 37 38 new Thread(new Runnable() { 39 @Override 40 public void run() { 41 System.out.println(Thread.currentThread().getName() + "线程开始执行..."); 42 try { 43 Thread.sleep(new Random().nextInt(2000)); 44 } catch (InterruptedException e) { 45 // TODO Auto-generated catch block 46 e.printStackTrace(); 47 } 48 System.out.println(Thread.currentThread().getName() + "线程执行完毕了..."); 49 } 50 51 }).start(); 52 53 while(Thread.activeCount() !=1) { 54 //自旋 55 } 56 57 58 System.out.println("所有的线程执行完毕了..."); 59 60 } 61 62 }
死锁
public class Demo3 { private Object obj1 = new Object(); private Object obj2 = new Object(); public void a() { synchronized (obj1) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (obj2) { System.out.println("a"); } } } public void b() { synchronized (obj2) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (obj1) { System.out.println("b"); } } } public static void main(String[] args) { Demo3 d = new Demo3(); new Thread(new Runnable() { @Override public void run() { d.a(); } }).start(); new Thread(new Runnable() { @Override public void run() { d.b(); } }).start(); } }
可以使用jdk自带的jconsole来检查死锁