Java多线程_三个方法解决线程锁死的问题

603 阅读2分钟

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

线程锁死

为什么会锁死?

同时有两个线程在等待,当为线程1开放之后锁起来,线程1继续去下面的线程2的锁,等于是压根没出去,自然就锁上了,线程2进不来。

等待线程由于唤醒线程所需要的条件 永远无法成立导致线程一直无法处于RUNNABLE状态,我们就称这个线程被锁死。

虽然死锁与锁死表现出来都是线程等待,无法继续完成任务,但是产生的条件是不同的,即使在不可能产生死锁的情况下也可能出现锁死,所以不能使用对付死锁的办法来解决锁死问题。

锁死包括信号丢失锁死和嵌套监视器锁死。

信号丢失锁死的典型案例是等待线程执行Object.wait()/Condition.await()前没有对保护条件进行判断,可能没有其他的线程更新相应的保护条件涉及的变量使其成立并通知线程,使得线程一直处于等待状态。

解决方法一:

等待方法

如下代码:

public void waitMethod(){
   synchronized( lock1) {
      synchronized( lock2){
         while( 条件 ){
            lock2.wait();
         }
      }
      //....
   }
}

解决方法二:

在主线程中手动进行线程的唤醒

如下代码:

		//解决方式二
		synchronized(s2) {
			s2.notifyAll();
		}

解决方式三:

使用Semaphore线程同步辅助类代替synchronized同步代码块,以其参数控制同时访问资源的线程个数。

如下代码:

import java.util.concurrent.Semaphore;

public class DeadLock { public static void main(String[] args) { Semaphore s1=new Semaphore(1); Semaphore s2=new Semaphore(0); Semaphore s3=new Semaphore(0); //线程一 new Thread() { public void run() { int count=100; while(count>0) { try { s1.acquire(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } count--; System.out.println(count); s2.release(); } } }.start(); //线程二 new Thread() { public void run() { int count=100; while(count>0) { try { s2.acquire(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } count--; System.out.println(count); s3.release(); } } }.start(); //线程三 new Thread() { public void run() { int count=100; while(count>0) { try { s3.acquire(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } count--; System.out.println(count); s1.release(); } } }.start(); } }