public class SimpleDeadlock {
/**
 * argv[0]: number of concurrently executed threads<br/>
*/
	public static void main(String argv[]) {
		Semaphore resources[] = new Semaphore[2];
		
		for (int i=0; i<resources.length; i++)
			resources[i] = new Semaphore(1);	
		
		for (int i=0; i<Integer.parseInt(argv[0]); i++)
			new Thread( new DeadLockingThread(resources) ).start();
	} //main()
} //class SimpleDeadlock

class DeadLockingThread implements Runnable {
	Semaphore resources[];
	
	public DeadLockingThread(Semaphore resources[]) {
		this.resources = new Semaphore[resources.length];
		for (int i=0; i<resources.length; i++)
			this.resources[i] = resources[i];
	} //constructor
	
	public void run() {
		System.out.println(Thread.currentThread().getName()+" is sleeping");
		try {
			Thread.sleep( (int) (Math.random() * 20000) );
		} //try
		catch (InterruptedException ie) {
			System.out.println("An InterruptedException caught\n"+ie.getMessage());
			ie.printStackTrace();
			System.exit(1);
		} //catch()
		int requestedResource=(int) (Math.random()*1.1);
		
		System.out.println(Thread.currentThread().getName()+" requests resource #"+requestedResource);
		resources[requestedResource].p();
		System.out.println(Thread.currentThread().getName()+" locks resource #"+requestedResource);
		try {
			Thread.sleep( (int) (Math.random() * 20000) );
		} //try
		catch (InterruptedException ie) {
			System.out.println("An InterruptedException caught\n"+ie.getMessage());
			ie.printStackTrace();
			System.exit(1);
		} //catch()
		
		//deadlock prone section begins
		int otherResource=Math.abs(requestedResource-1); 
		System.out.println(Thread.currentThread().getName()+" requests resource #"+otherResource);
		resources[otherResource].p();
		System.out.println(Thread.currentThread().getName()+" locks resource #"+otherResource);
		try {
			Thread.sleep( (int) (Math.random() * 20000) );
		} //try
		catch (InterruptedException ie) {
			System.out.println("An InterruptedException caught\n"+ie.getMessage());
			ie.printStackTrace();
			System.exit(1);
		} //catch()
		resources[otherResource].v();
		System.out.println(Thread.currentThread().getName()+" released resource #"+otherResource);
		//deadlock prone section ends
		resources[requestedResource].v();
		System.out.println(Thread.currentThread().getName()+" released resource #"+requestedResource);
	} //run()
} //class DeadLockingThread
