Java多线程的死锁问题

博客探讨了生产者 - 消费者场景下的死锁问题。一个消费者和生产者时不会死锁,两个消费者和一个生产者时可能因所有线程进入等待池而死锁。指出synchronized和wait notify导致死锁的不同原因,并认为可通过检测持有请求循环来检测wait notify导致的死锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import java.util.*;

public class Consumer implements Runnable{
	List<Integer> cache;
	
	public Consumer(List<Integer> cache)
	{
		this.cache = cache;
	}
	public void run()
	{
		while(true)
		{
			consume();
		}
	}
	private void consume()
	{
		synchronized(cache)
		{
			try {
				while(cache.isEmpty())
				{
					cache.wait();
				}
				System.out.println("Consumer consumed ["+cache.remove(0)+"]");
				cache.notifyAll();
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}
}
import java.util.List;
import java.util.Random;

public class Producer implements Runnable {
	List<Integer> cache;
	
	public Producer(List<Integer> cache)
	{
		this.cache = cache;
	}
	
	public void run()
	{
		while(true)
		{
			produce();
		}
	}
	private void produce()
	{
		synchronized(cache)
		{
			try
			{
				while(cache.size() == 1)
				{
					cache.wait();
				}
				Thread.sleep(1000);
				cache.add(new Random().nextInt());
				
				cache.notifyAll();
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}
}
import java.util.*;

public class Main {
	public static void main(String[]args)throws Exception
	{
		List<Integer> cache = new ArrayList<Integer>();
		new Thread(new Consumer(cache)).start();
		new Thread(new Producer(cache)).start();
	}
}
import java.util.*;

public class Main2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Integer> cache = new ArrayList<Integer>();
		new Thread(new Consumer(cache)).start();
		new Thread(new Consumer(cache)).start();
		new Thread(new Consumer(cache)).start();
		
		new Thread(new Producer(cache)).start();
		new Thread(new Producer(cache)).start();
		new Thread(new Producer(cache)).start();
	}

}

只有一个消费者和生产者的时候,等待池中只有一个线程,不会产生闭环,因而不会发生死锁

当有两个消费者c1,c2,一个生产者p1。

首先根据main中顺序,启动c1,c2,此时cache为空,c1,c2等待。

启动p1,size==0,p1获取锁并且设置cache数据,notify唤醒等待的某个线程假设为c1,c1

无法调用synchronized方法因而进入锁池,p1释放锁,继续循环获取锁并且此时size==1执行wait进入等待池

锁池中现在是c1,c1竞争到锁消费数据,假设执行notify取出c2进入锁池,因为c1已经消费过,size==0,执行wait进入等待池

c1最后也会进入等待池。所有的线程都进入等待池,程序发生死锁。

 

一般的synchronized导致死锁是因为不同的线程加锁时相互交叉导致互相堵塞

而wait notify导致的死锁是因为使得所有的线程同时进入等待池导致不同线程无法相互唤醒

因而我认为能依靠检测持有请求循环来检测后者的死锁,因为当所有的线程都进入某个对象的等待池,自然就会发生死锁,这时我们也能够发现死锁的原因了。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值