Java多线程(五)线程死锁
死锁
1.死锁的理解:不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
2.说明:
1)出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续
2)我们使用同步时,要避免出现死锁。
1 public class ThreadTest { 2 3 public static void main(String[] args) { 4 5 StringBuffer s1 = new StringBuffer(); 6 StringBuffer s2 = new StringBuffer(); 7 8 9 new Thread(){ 10 @Override 11 public void run() { 12 13 synchronized (s1){ 14 15 s1.append("a"); 16 s2.append("1"); 17 18 try { 19 Thread.sleep(100); 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 } 23 24 synchronized (s2){ 25 s1.append("b"); 26 s2.append("2"); 27 28 System.out.println(s1); 29 System.out.println(s2); 30 } 31 } 32 } 33 }.start(); 34 35 36 new Thread(new Runnable() { 37 @Override 38 public void run() { 39 synchronized (s2){ 40 41 s1.append("c"); 42 s2.append("3"); 43 44 try { 45 Thread.sleep(100); 46 } catch (InterruptedException e) { 47 e.printStackTrace(); 48 } 49 50 synchronized (s1){ 51 s1.append("d"); 52 s2.append("4"); 53 54 System.out.println(s1); 55 System.out.println(s2); 56 } 57 } 58 } 59 }).start(); 60 } 61 }
死锁的演示
1 package com.atguigu.java1; 2 //死锁的演示 3 class A { 4 public synchronized void foo(B b) { //同步监视器:A类的对象:a 5 System.out.println("当前线程名: " + Thread.currentThread().getName() 6 + " 进入了A实例的foo方法"); // ① 7 // try { 8 // Thread.sleep(200); 9 // } catch (InterruptedException ex) { 10 // ex.printStackTrace(); 11 // } 12 System.out.println("当前线程名: " + Thread.currentThread().getName() 13 + " 企图调用B实例的last方法"); // ③ 14 b.last(); 15 } 16 17 public synchronized void last() {//同步监视器:A类的对象:a 18 System.out.println("进入了A类的last方法内部"); 19 } 20 } 21 22 class B { 23 public synchronized void bar(A a) {//同步监视器:b 24 System.out.println("当前线程名: " + Thread.currentThread().getName() 25 + " 进入了B实例的bar方法"); // ② 26 // try { 27 // Thread.sleep(200); 28 // } catch (InterruptedException ex) { 29 // ex.printStackTrace(); 30 // } 31 System.out.println("当前线程名: " + Thread.currentThread().getName() 32 + " 企图调用A实例的last方法"); // ④ 33 a.last(); 34 } 35 36 public synchronized void last() {//同步监视器:b 37 System.out.println("进入了B类的last方法内部"); 38 } 39 } 40 41 public class DeadLock implements Runnable { 42 A a = new A(); 43 B b = new B(); 44 45 public void init() { 46 Thread.currentThread().setName("主线程"); 47 // 调用a对象的foo方法 48 a.foo(b); 49 System.out.println("进入了主线程之后"); 50 } 51 52 public void run() { 53 Thread.currentThread().setName("副线程"); 54 // 调用b对象的bar方法 55 b.bar(a); 56 System.out.println("进入了副线程之后"); 57 } 58 59 public static void main(String[] args) { 60 DeadLock dl = new DeadLock(); 61 new Thread(dl).start(); 62 63 64 dl.init(); 65 } 66 }
Lock(锁)
- 从JDK5.0开始,Java提供了更强大的线程同步机制——通过显示定义同步锁对象来实现同步。同步锁使用Lock对象充当。
- java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
- ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。
1 package com.atguigu.java1; 2 3 import java.util.concurrent.locks.ReentrantLock; 4 5 /** 6 * 解决线程安全问题的方式三:Lock锁 --- JDK5.0新增 7 * 8 * 1. 面试题:synchronized 与 Lock的异同? 9 * 相同:二者都可以解决线程安全问题 10 * 不同:synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器 11 * Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock()) 12 * 13 * 2.优先使用顺序: 14 * Lock 同步代码块(已经进入了方法体,分配了相应资源) 同步方法(在方法体之外) 15 * 16 * 17 * 面试题:如何解决线程安全问题?有几种方式 18 */ 19 class Window implements Runnable{ 20 21 private int ticket = 100; 22 //1.实例化ReentrantLock 23 private ReentrantLock lock = new ReentrantLock(); 24 25 @Override 26 public void run() { 27 while(true){ 28 try{ 29 30 //2.调用锁定方法lock() 31 lock.lock(); 32 33 if(ticket > 0){ 34 35 try { 36 Thread.sleep(100); 37 } catch (InterruptedException e) { 38 e.printStackTrace(); 39 } 40 41 System.out.println(Thread.currentThread().getName() + ":售票,票号为:" + ticket); 42 ticket--; 43 }else{ 44 break; 45 } 46 }finally { 47 //3.调用解锁方法:unlock() 48 lock.unlock(); 49 } 50 51 } 52 } 53 } 54 55 public class LockTest { 56 public static void main(String[] args) { 57 Window w = new Window(); 58 59 Thread t1 = new Thread(w); 60 Thread t2 = new Thread(w); 61 Thread t3 = new Thread(w); 62 63 t1.setName("窗口1"); 64 t2.setName("窗口2"); 65 t3.setName("窗口3"); 66 67 t1.start(); 68 t2.start(); 69 t3.start(); 70 } 71 }

浙公网安备 33010602011771号