多生產者-消費者中假死現象的處理

z1340954953發表於2018-05-08

單個的生產者-消費者模型

package com.ftf.thread.lock;

public class Factory {
	private volatile boolean flag = true;
	private Object obj = new Object();
	public void setValue(){
		synchronized (obj) {
			try {
			while(!flag){
					obj.wait();
			}
			System.out.println("生產者生產資料......");
			Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			flag = false;
			obj.notify();
		}
	}
	public void getValue(){
		synchronized (obj) {
			try {
			while(flag){
				obj.wait();
			}
			System.out.println("消費者消費資料....");
			Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			flag = true;
			obj.notify();
		}
	}
	public static void main(String[] args) {
		final Factory ft = new Factory();
		Thread product = new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					ft.setValue();
				}
			}
		});
		Thread customer = new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){
					ft.getValue();
				}
			}
		});
		customer.start();
		product.start();
	}
}

但是如果,多啟動一個生產者消費者,或者生產者執行緒,就會出現執行緒假死現象,生產者/消費者執行緒不在執行。

public static void main(String[] args) {
		final Factory ft = new Factory();
		Thread product = new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					ft.setValue();
				}
			}
		});
		Thread customer = new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					ft.getValue();
				}
			}
		});
		Thread customer1 = new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					ft.getValue();
				}
			}
		});
		Thread customer2 = new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					ft.getValue();
				}
			}
		});
		customer1.start();
		customer2.start();
		customer.start();
		product.start();
	}

結果:


原因:在於notify在多生產-多消費者情況下,喚醒的可能是同類,導致生產者或消費者執行緒沒有競爭鎖的機會,出現假死,

解決:notify改為notifyAll,如果使用的是lock鎖的話,多生產者消費者模型中,使用signalAll來解決假死現象

相關文章