Java多线程进阶干货(2)

Wesley13
• 阅读 287

问题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源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
2个月前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。 language JavaScript "name": "vuecliversion2", "version": "1.0.0", "desc
技术小男生 技术小男生
2个月前
linux环境jdk环境变量配置
1:编辑系统配置文件vi /etc/profile2:按字母键i进入编辑模式,在最底部添加内容: JAVAHOME/opt/jdk1.8.0152 CLASSPATH.:$JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools.jar PATH$JAVAHOME/bin:$PATH3:生效配置
光头强的博客 光头强的博客
2个月前
Java面向对象试题
1、 请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。 创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现 接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿 吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
2个月前
css问题
1、 在IOS中图片不显示(给图片加了圆角或者img没有父级) <div<img src""/</div div {width: 20px; height: 20px; borderradius: 20px; overflow: h
Jacquelyn38 Jacquelyn38
1年前
你不可不知的JS面试题(第二期)
1、什么是继承?子类可以使用父类的所有功能,并且对功能进行扩展。 新增方法 改用方法 (1)、ES6使用extends子类继承父类的方法。 // 父类     class A         constructor(name)             this.name name;                  getNa
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录 问题 用navicat导入数据时,报错: 原因这是因为当前的MySQL不支持datetime为0的情况。 解决修改sql\mode: sql\mode:SQL Mode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。 全局s
Wesley13 Wesley13
1年前
java锁学习(二)
类锁 -- 类锁 !!!! java类有很多对象 ,但是只有一个class对象 !!!! 所以,类锁,就是针对当前类的Class对象的锁 类锁同一时刻只能被一个对象获取 1. synchronized放在static方法上(静态锁) 2. synchronized放在class对象上 ### 静态锁 class SyncClassSt
Wesley13 Wesley13
1年前
java并发相关(四)——关于synchronized的可重入性,线程切换实现原理与是否公平锁
**一、可重入性**   关于synchronized的可重入性的证明,我们可以通过A类内写两个同步方法syncA(),syncB()。然后syncA内调用syncB,调用syncA发现代码可正常执行,来证明这一点。   当处于无锁阶段时,划掉,都重入了不可能处于无锁。   当处于偏向锁阶段时,由之前对偏向锁的解释可知,偏向当前线程id是,当前线程可直
Wesley13 Wesley13
1年前
java中多态的实现机制
多态的概念:   简单来说就是事物在运行过程中存在的不同状态,即父类或接口定义的引用变量指向子类或具体实现类的实例对象。程序调用方法在运行期才进行动态绑定,而不是引用变量的类型中定义的方法。 多态存在的前提: 1、存在继承关系,子类继承父类; 2、子类重写父类的方法; 3、父类引用指向子类对象。 具体实例: 1、定义一个父类:Animal
Easter79 Easter79
1年前
synchronize底层原理
1、普通同步方法,锁是当前实例对象 2、静态同步方法,锁是当前类的class对象 3、同步方法块,锁是括号里面的对象 **synchronize底层原理:** Java 虚拟机中的同步(Synchronization)基于进入和退出Monitor对象实现, 无论是显式同步(有明确的 monitorenter 和 monitorexit 指令,即同步代
Wesley13 Wesley13
1年前
java向上转型和向下转型1
  在java继承体系中,认为父类(超类)在上层,子类在下层(派生类) ,向上转型就是把子类对象转成父类对象。 1 public class Father { 2 public void eat(){ 3 System.out.println("我是父类的方法吃。。。。。"); 4 }