一、静态同步方法synchronized 和 synchronized(this)同步代码块
(一)、静态同步方法synchronize
package com.it.po.thread06; public class Service1 { synchronized public static void printA(){ try { System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printA..."); Thread.sleep(2000); System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printA..."); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public static void printB(){ try { System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB..."); Thread.sleep(2000); System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB..."); } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.it.po.thread06; public class MyThread01_1 extends Thread { @Override public void run() { super.run(); Service1.printA(); } }
package com.it.po.thread06; public class MyThread01_2 extends Thread { @Override public void run() { super.run(); Service1.printB(); } }
package com.it.po.thread06; import com.it.po.thread05.Task1; public class Run01 { public static void main(String[] args){ MyThread01_1 my1 = new MyThread01_1(); MyThread01_2 my2 = new MyThread01_2(); my1.setName("A"); my2.setName("B"); my1.start(); my2.start(); } }
线程:A 进来了 printA...
线程:A 进来了 printA...
线程:B 进来了 printB...
线程:B 进来了 printB...
总结: synchronized 加到带static的方法上是给类加锁,和synchronized 加到非static的方法上(是给对象加锁)没有什么区别。
(二)、静态同步方法synchronize 和非static 的synchronize 方法
package com.it.po.thread06; public class Service2 { synchronized public static void printA(){ try { System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printA..."); Thread.sleep(2000); System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printA..."); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public static void printB(){ try { System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB..."); Thread.sleep(2000); System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB..."); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public void printC(){ try { System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB..."); Thread.sleep(2000); System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB..."); } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.it.po.thread06; public class MyThread02_1 extends Thread { @Override public void run() { super.run(); Service1.printA(); } }
package com.it.po.thread06; public class MyThread02_2 extends Thread { @Override public void run() { super.run(); Service1.printA(); } }
package com.it.po.thread06; public class MyThread02_3 extends Thread { @Override public void run() { super.run(); Service2 service2 = new Service2(); service2.printC(); } }
package com.it.po.thread06; public class Run02 { public static void main(String[] args){ MyThread02_1 my1 = new MyThread02_1(); MyThread02_2 my2 = new MyThread02_2(); MyThread02_3 my3 = new MyThread02_3(); my1.setName("A"); my2.setName("B"); my3.setName("C"); my3.start(); my1.start(); my2.start(); } }
线程:A 进来了 printA...
线程:C 进来了 printB...
线程:A 进来了 printA...
线程:B 进来了 printA...
线程:C 进来了 printB...
线程:B 进来了 printA...
区别:锁类和锁对象的。
(三)、静态方法同步代码块的特点
package com.it.po.thread06; public class Service3 { public static void printA(){ synchronized(Service2.class) { try { System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printA..."); Thread.sleep(2000); System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printA..."); } catch (InterruptedException e) { e.printStackTrace(); } } } synchronized public static void printB(){ synchronized(Service2.class) { try { System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printB..."); Thread.sleep(2000); System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printB..."); } catch (InterruptedException e) { e.printStackTrace(); } } } synchronized public void printC(){ synchronized(Service2.class) { try { System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printB..."); Thread.sleep(2000); System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printB..."); } catch (InterruptedException e) { e.printStackTrace(); } } } }
package com.it.po.thread06; public class MyThread03_1 extends Thread { private Service3 service3; public MyThread03_1(Service3 service3) { this.service3 = service3; } @Override public void run() { super.run(); service3.printA(); } }
package com.it.po.thread06; public class MyThread03_2 extends Thread { private Service3 service3; public MyThread03_2(Service3 service3) { this.service3 = service3; } @Override public void run() { super.run(); service3.printB(); } }
package com.it.po.thread06; public class MyThread03_3 extends Thread { private Service3 service3; public MyThread03_3(Service3 service3) { this.service3 = service3; } @Override public void run() { super.run(); service3.printC(); } }
package com.it.po.thread06; public class Run03 { public static void main(String[] args){ Service3 service3 = new Service3(); MyThread03_1 my1 = new MyThread03_1(service3); MyThread03_2 my2 = new MyThread03_2(service3); MyThread03_3 my3 = new MyThread03_3(service3); my1.setName("A"); my2.setName("B"); my3.setName("C"); my3.start(); my1.start(); my2.start(); } }
线程:A 进来了 printA...
线程:A 进来了 printA...
线程:B 进来了 printB...
线程:B 进来了 printB...
线程:C 进来了 printB...
线程:C 进来了 printB...
修改如下
package com.it.po.thread06; public class MyThread03_1 extends Thread { private Service3 service3; public MyThread03_1(Service3 service3) { this.service3 = service3; } @Override public void run() { super.run(); // service3.printA(); Service3.printA(); } }
线程:A 进来了 printA...
线程:A 进来了 printA...
线程:C 进来了 printB...
线程:C 进来了 printB...
线程:B 进来了 printB...
线程:B 进来了 printB...
注意:锁定的是类。
二、同步方法无限等待与解决
package com.it.po.thread06; public class Service4 { synchronized public void methodA(){ System.out.println("线程 "+Thread.currentThread().getName()+" 进入methodA 。。"); boolean po=true; while (po){ } System.out.println("线程 "+Thread.currentThread().getName()+" 走出methodA 。。"); } synchronized public void methodB(){ System.out.println("线程 "+Thread.currentThread().getName()+" 进入methodB 。。"); System.out.println("线程 "+Thread.currentThread().getName()+" 走出methodB 。。"); } }
package com.it.po.thread06; public class MyThread04_1 extends Thread { private Service4 service4; public MyThread04_1(Service4 service4) { this.service4 = service4; } @Override public void run() { super.run(); service4.methodA(); } }
package com.it.po.thread06; public class MyThread04_2 extends Thread { private Service4 service4; public MyThread04_2(Service4 service4) { this.service4 = service4; } @Override public void run() { super.run(); service4.methodB(); } }
package com.it.po.thread06; public class Run04 { public static void main(String[] args){ Service4 service4 = new Service4(); MyThread04_1 my1 = new MyThread04_1(service4); MyThread04_2 my2 = new MyThread04_2(service4); my1.setName("A"); my2.setName("B"); my1.start(); my2.start(); } }

解决无限等锁办法:
package com.it.po.thread06; import com.sun.org.apache.bcel.internal.generic.NEW; public class Service4 { Object object1=new Object(); Object object2=new Object(); public void methodA(){ synchronized(object1) { System.out.println("线程 " + Thread.currentThread().getName() + " 进入methodA 。。"); boolean po = true; while (po) { } System.out.println("线程 " + Thread.currentThread().getName() + " 走出methodA 。。"); } } public void methodB(){ synchronized(object2) { System.out.println("线程 " + Thread.currentThread().getName() + " 进入methodB 。。"); System.out.println("线程 " + Thread.currentThread().getName() + " 走出methodB 。。"); } } }
三、多线程的死锁
多线程的死锁是非常经典的问题,不同的线程在等待不可能释放的锁,导致假死状态。
package com.it.po.thread06; public class DealThread implements Runnable { public String username; public Object lock1=new Object(); public Object lock2=new Object(); public void setUsername(String username){ this.username=username; } @Override public void run() { if("a".equals(username)){ synchronized (lock1) { try { System.out.println("a1: username= "+username); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2) { System.out.println("a2: username= "+username); } } } if("b".equals(username)){ synchronized (lock2) { try { System.out.println("b1: username= "+username); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1) { System.out.println("b2: username= "+username); } } } } }
package com.it.po.thread06; import com.sun.org.apache.bcel.internal.generic.NEW; public class RunDeal { public static void main(String[] args) throws InterruptedException { DealThread t1 = new DealThread(); t1.setUsername("a"); Thread t2 = new Thread(t1); t2.start(); Thread.sleep(50); t1.setUsername("b"); Thread t3 = new Thread(t1); t3.start(); } }


1.在jdkd的bin文件下打开命令: 输入jps

2.记住程序 RunDeal 的id值 97404 继续输入命令:jstack+ id


确实发生死锁。
注意:实际开发中,没有例子中 synchronized 的嵌套,也是会发生死锁的,死锁与嵌套不嵌套没有关系。
浙公网安备 33010602011771号