zoukankan      html  css  js  c++  java
  • Java中的死锁问题

    死锁问题:

      例如有两个线程, 线程1与线程2. 

      线程1在执行的过程中, 要锁定对象1, 2才能完成整个操作, 首先锁定对象1, 再锁定对象2.

      线程2在执行的过程中, 要锁定对象2, 1才能完成整个操作, 首先锁定对象2, 再锁定对象1.

      某时刻, 线程1已经拥有对象1的锁, 要是再拥有对象2的锁就能完成整个操作, 可惜了, 你等待着的对象2的锁已经被别人拥有了, 执行不下去了.

      此时刻, 线程2已经拥有对象2的锁, 要是再拥有对象1的锁就能完成整个操作, 可惜了, 你等待着的对象1的锁已经被别人拥有了, 执行不下去了.

      两个对象都已经锁了, 腰都要求对象放锁, 不可能, 那就都等着吧............

    死锁例程:

    public class DeadLock implements Runnable{
    	public int flag ;
    	static Object o1 = new Object();
    	static Object o2 = new Object();
    	@Override
    	public void run() {
    		System.out.println("flag: "+flag);
    		if(flag == 1) {
    			synchronized(o1){
    				try {
    					Thread.sleep(500);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    			synchronized(o2){
    				System.out.println("1");
    			}
    		}
    		if(flag == 0){
    			synchronized(o2){
    				try {
    					Thread.sleep(500);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    			synchronized(o1){
    				System.out.println("0");
    			}
    		}
    	}
    	public static void main(String[] args) {
    		DeadLock de1 = new DeadLock();
    		DeadLock de2 = new DeadLock();
    		de1.flag = 1;
    		de2.flag = 0;
    		Thread t1 = new Thread(de1);
    		Thread t2 = new Thread(de2);
    		t1.start();
    		t2.start();
    	}
    }
    

     Demo_1:

    public class TT1 implements Runnable {
    	public int b;
    	public synchronized void m1() throws Exception { // 只是方法锁定而已, 别的线程无法执行它
    		b = 1000;                                    // 其他的线程无法再调用它(方法里面的东西(语句))
    		Thread.sleep(5000);
    		System.out.println("b = "+b);
    	}
    	public void m2() {
    		System.out.println(b);
    	}
    	@Override
    	public void run() {
    		try {
    			m1();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	public static void main(String[] args) throws Exception{
    		TT1 tt1 = new TT1();
    		Thread t = new Thread(tt1);
    		t.start();
    		Thread.sleep(1000);
    		tt1.m2();
    	}
    }
    

     运行结果:

    1000
    b = 1000

    Demo_2:

    public class TT2 implements Runnable {
    	public int b = 100;
    	public synchronized void m1() throws Exception { // 互斥, 在某一时刻, 保证只有一个线程进入我们这个方法里面
    		b = 1000;                                    // 但是, 不保证其他的线程是不是能够进入到另外一个方法里面
    		Thread.sleep(5000);
    		System.out.println("b = "+b);
    	}
    	public void m2() throws Exception {
    		Thread.sleep(2500);
    		b = 2000;
    	}
    	@Override
    	public void run() {
    		try {
    			m1();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	public static void main(String[] args) throws Exception{
    		TT2 tt = new TT2();
    		Thread t = new Thread(tt);
    		t.start();
    		tt.m2();
    	}
    }
    

     运行结果:

    b = 2000

      在Demo_2中, 如果在 m2() 的方法也加 synchronized. 同时在主方法中的 tt.m2() 后面加一句: System.out.println(tt.b);

    则, 运行结果为:

    1000

    b = 1000 // 这句话执行得比较快.

    【注】:当某个对象调用了同步方法时, 该对象上的其它同步方法必须等待该同步方法执行完毕后, 才能被执行.

    【注】:其实, 写一个同步的东西是挺困难的. 因为每一个方法要不要同步, 你要考虑得非常清楚.如果一个方法

        做了同步, 另外一个方法没有做同步, 那么你要记住一点: 别的线程可以自由得访问那个非同步的方法,

        并且可能会对你那个同步的方法产生影响, 所以你要保护好某一个类里面的某一个对象的话, 或者说你

        要保护好需要同步的那个对象的话, 你必须对访问这个对象的所有方法仔细考虑, 加不加同步, 加了同

        步, 很有可能效率很低, 不加同步, 有可能产生数据不一致的现象.

  • 相关阅读:
    POJ 3292 Semi-prime H-numbers (素数筛法变形)
    POJ 1845 Sumdiv (整数拆分+等比快速求和)
    POJ 2635 The Embarrassed Cryptographer(大数求余)
    POJ 2115 C Looooops (扩展欧几里德 + 线性同余方程)
    poj3071
    poj2486
    poj1947
    POJ 1159
    POJ 1845
    poj3282
  • 原文地址:https://www.cnblogs.com/bosongokay/p/6863281.html
Copyright © 2011-2022 走看看