问题1:子类可以调用父类的同步方法吗?
/** *  * 一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象的锁, * 再次申请时,仍然会得到该对象的锁,也就是说synchronized获得的锁是可重入的 * * 这里是继承中有可能发生的情形,子类调用父类的同步方法 */public class Test09 {    synchronized void a(){        System.out.println("a....start..");    }    public static void main(String[] args) {        T t = new T();        t.b();    }    static class T extends Test09{        synchronized void b(){            System.out.println("b...start...");            super.a();        }    }}
运行结果是:
问题2:程序在执行过程中,如果出现异常,锁会怎么样?
/** * 程序在执行过程中,如果出现异常,默认情况锁会被释放 * 所以,在并发处理过程中,有异常要多加小心,不然可能会发生不一致的情况, * 比如在一个web app处理过程中,多个servlet线程共同访问同一个资源,这时,如果异常处理不合适 * 在第一个线程中抛出异常,其他线程就会进入同步代码区,有可能会访问到异常产生时的数据 * 因此要非常小心的处理同步业务逻辑中的异常 */public class Test10 {    int count = 0;    synchronized void m1() {        System.out.println(Thread.currentThread().getName() + "  start....");        while(true){            count ++;            System.out.println(Thread.currentThread().getName() + "  start...." + count);            try {                Thread.sleep(2000);            } catch (InterruptedException e) {                e.printStackTrace();            }            if(count == 5) {                int a = count / 0;                try {                }catch (Exception e){                }            }        }    }    public static void main(String[] args) {        Test10 test10 = new Test10();        new Thread(new Runnable() {            @Override            public void run() {                test10.m1();            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                test10.m1();            }        }).start();    }}
运行结果:
问题3:如下程序执行的结果是?
/** * 锁定某对象o,如果o的属性发生改变,不影响锁的使用 * 但是如果o变成另外一个对象,则锁定的对象发生改变 * 应该避免将锁定的对象变成另外一个对象 */public class Test {    Object o = new Object();    void m() {        synchronized (o){            while (true){                try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println(Thread.currentThread().getName());            }        }    }    public static void main(String[] args) {        Test test = new Test();        new Thread(new Runnable() {            @Override            public void run() {                test.m();            }        },"jjj").start();        try {            Thread.sleep(3000);        } catch (InterruptedException e) {            e.printStackTrace();        }        test.o = new Object(); // 锁对象发生改变,所以t2线程得以执行,如果注释掉这句话,线程2将永远得不到执行        new Thread(new Runnable() {            @Override            public void run() {                test.m();            }        },"ddddd").start();    }}
执行结果是:
问题4:编程经验
/** * 不要以字符串常量作为锁定对象 * 在下面的例子中,m1和m2其实锁定的是一个对象 * 这种情况还会发生比较诡异的现象,比如你用到一个类库,在该类库中代码锁定了字符串常量“Hello”, * 但是你读不到源码,所以你在自己的代码中也锁定了“Hello”,这时候就可能发生非常诡异的死锁阻塞, * 因为你的程序和你用到的类库不经意间使用了同一把锁 * * jetty */public class Test {    String h1 = "Hello";    String h2 = "Hello";    void m1 (){        synchronized (h1){        }    }    void m2() {        synchronized (h2){        }    }    public static void main(String[] args) {    }
本文分享自微信公众号 - Java学习进阶手册(javastudyup)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
 
  
  
  
 
 
  
 