1 定义: 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,形成线程的死锁
2 过程:例如:主线程利用对象占用了一个同步锁,然后执行sleep方法。如果在sleep过程中没有其他线程进入,则主线程继续执行占用后面的同步锁,不会产生死锁;但如果有其他线程进入,其他线程先占用了后面的同步锁,再去要求第一个同步锁时就产生死锁。
3 Object类中的三个方法:必须放在同步代码块中
wait():当前线程挂起并放弃cpu,同步资源使其他线程可访问并修改共享资源,而当前线程排队等候
notify():唤醒正在排队等待同步资源的线程最高者结束等待。因为是队列是先进先出的,所以可以配合wait方法实现交替打印。
notifyAll():唤醒正在排队等待同步资源的所有线程结束等待
4 释放锁:wait()(执行到此方法,此线程等待,直到其他线程执行notify方法将其唤醒,唤醒后继续执行wait之后的代码
不释放锁:sleep()(该线程睡眠,仍占据cpu,其他线程进来后也睡眠,只有该线程执行完,cpu才交给别的线程),yield(),suspend()
package lianxi1; class Client{ int product; public synchronized void addproduct(){ if(product>=20){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else{ product++; System.out.println(Thread.currentThread().getName()+"正在生产第"+product+"号产品"); } notifyAll(); } public synchronized void removeproduct(){ if(product<=0){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else{ System.out.println(Thread.currentThread().getName()+"正在消费第"+product+"号产品"); product--; notifyAll(); } } } class Producer implements Runnable{ Client clerk; public Producer(Client clerk) { super(); this.clerk = clerk; } @Override public void run() { while(true){ try { Thread.sleep(120); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } clerk.addproduct(); } } } class Consumer implements Runnable{ Client clerk; public Consumer(Client clerk) { super(); this.clerk = clerk; } @Override public void run() { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } while(true){ clerk.removeproduct(); } } } public class TestProConsumer { public static void main(String[] args) { Client clerk = new Client(); Producer p1 = new Producer(clerk);//clerk确保是同一把锁 Consumer c1 = new Consumer(clerk); Thread t1 = new Thread(p1); Thread t3 = new Thread(p1); Thread t2 = new Thread(c1); t1.setName("生产者1"); t3.setName("生产者2"); t2.setName("消费者1"); t1.start(); t2.start(); t3.start(); } }