Java 死锁的简单实例

虽然网上有各种关于死锁的说法,但是却没有一个实际的案例来阐述这个死锁到底是什么样的


那么这里有一个简单的死锁实例:

        线程t1需要先使用扫描仪扫描文件、再使用打印机打印文件,之后工作完毕

        线程t2需要先使用打印机打印文件、再使用扫描仪扫描文件,之后工作完毕

如果是正常的工作秩序,那应该是t1先拥有扫描仪的使用权,而t2呢则拥有打印机的使用权,此时则大家秩序井然的工作直至工作完毕

但死锁往往是发生在一些意外的情况,如t1要先扫描文件但却拥有了打印机的使用权限,而没有扫描仪的使用权限,t2则相反,此时大家都在等待对方使用完成后,让出使用权限,这样无限制的等待下去,就造成了我们所谓的“死锁”


PS:这里不同的调度方式,结果也会不同。例如使用权都是t1,或都是t2等


代码如下:

public class Test implements Runnable {
	
	Scanner scanner;
	Printer printer;
	
	int scannerTurn = 2, printerTurn = 1;
	boolean isScannerT1Done = false, isScannerT2Done = false;
	boolean isPrinterT1Done = false, isPrinterT2Done = false;
	
	Test(Scanner s, Printer p) {
		scanner = s;
		printer = p;
	}
    
    public static void main(String[] args) {
        new Test(new Scanner(), new Printer()).run();
    }
  
    @Override  
    public void run() {
    	new Thread("t1") {
    		@Override
    		public void run() {
    			// TODO Auto-generated method stub
    			//扫描和打印都完成,工作结束
    			while(!(isScannerT1Done && isPrinterT1Done)) {
	    			synchronized (scanner) {
	    				if(scannerTurn == 1) {
	    					if(!isScannerT1Done) {
	    						scanner.work(getName());

	    						scannerTurn = 2;
	    						isScannerT1Done = true;
	    					}
	    				}
						else
							try {
		    					System.out.println(getName() + " is waiting for printer...");
		    					//没有使用权限,等待通知
								scanner.wait();
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}

        				//通知等待使用扫描仪的线程,现在打印机可以使用了
    					scanner.notifyAll();
					}
    				
        			synchronized (printer) {
        				if(printerTurn == 1 && !isPrinterT1Done) {
	        				printer.work(getName());
	        				System.out.println(getName() + " is done!");
	        				
	        				printerTurn = 2;
	        				isPrinterT1Done = true;
        				}

        				//通知等待使用打印机的线程,现在打印机可以使用了
    					printer.notifyAll();
    				}
    			}
    		}
    	}.start();

    	new Thread("t2") {
    		@Override
    		public void run() {
    			// TODO Auto-generated method stub
    			//打印和扫描都完成,工作结束
    			while(!(isScannerT2Done && isPrinterT2Done)) {
    				synchronized (printer) {
	    				if(printerTurn == 2) {
	    					if(!isPrinterT2Done) {
	    						printer.work(getName());
		    					
	    						printerTurn = 1;
	    						isPrinterT2Done = true;
	    					}
	    				}
						else
							try {
		    					System.out.println(getName() + " is waiting for scanner...");
		    					//没有使用权限,等待通知
								printer.wait();
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}

        				//通知等待使用打印机的线程,现在打印机可以使用了
    					printer.notifyAll();
					}
    				
        			synchronized (scanner) {
        				if(scannerTurn == 2 && !isScannerT2Done) {
	        				scanner.work(getName());
	        				System.out.println(getName() + " is done!");
	        				
	        				isScannerT2Done = true;
	        				scannerTurn = 1;
        				}

        				//通知等待使用扫描仪的线程,现在打印机可以使用了
    					scanner.notifyAll();
    				}
    			}
    		}
    	}.start();
    }
    
    static class Scanner {
    	void work(String s) {
    		System.out.println(s + " scan successful!");
    	}
    }
    
    static class Printer {
    	void work(String s) {
    		System.out.println(s + " print successful!");
    	}
    }
}


猜你喜欢

转载自blog.csdn.net/aa54682002/article/details/46988807