Java多线程进阶干货(2)

Wesley13
• 阅读 436

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

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
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:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
你不可不知的JS面试题(第二期)
1、什么是继承?子类可以使用父类的所有功能,并且对功能进行扩展。新增方法改用方法(1)、ES6使用extends子类继承父类的方法。// 父类    class A        constructor(name)            this.name name;                getNa
Wesley13 Wesley13
2年前
java锁学习(二)
类锁类锁!!!!java类有很多对象,但是只有一个class对象!!!!所以,类锁,就是针对当前类的Class对象的锁类锁同一时刻只能被一个对象获取1.synchronized放在static方法上(静态锁)2.synchronized放在class对象上静态锁classSyncClassSt
Wesley13 Wesley13
2年前
java并发相关(四)——关于synchronized的可重入性,线程切换实现原理与是否公平锁
一、可重入性  关于synchronized的可重入性的证明,我们可以通过A类内写两个同步方法syncA(),syncB()。然后syncA内调用syncB,调用syncA发现代码可正常执行,来证明这一点。  当处于无锁阶段时,划掉,都重入了不可能处于无锁。  当处于偏向锁阶段时,由之前对偏向锁的解释可知,偏向当前线程id是,当前线程可直
Wesley13 Wesley13
2年前
java中多态的实现机制
多态的概念:  简单来说就是事物在运行过程中存在的不同状态,即父类或接口定义的引用变量指向子类或具体实现类的实例对象。程序调用方法在运行期才进行动态绑定,而不是引用变量的类型中定义的方法。多态存在的前提:1、存在继承关系,子类继承父类;2、子类重写父类的方法;3、父类引用指向子类对象。具体实例:1、定义一个父类:Animal
Easter79 Easter79
2年前
synchronize底层原理
1、普通同步方法,锁是当前实例对象2、静态同步方法,锁是当前类的class对象3、同步方法块,锁是括号里面的对象synchronize底层原理:Java虚拟机中的同步(Synchronization)基于进入和退出Monitor对象实现,无论是显式同步(有明确的monitorenter和monitorexit指令,即同步代
Wesley13 Wesley13
2年前
java多线程(四)之同步机制
1.同步的前提  多个线程  多个线程使用的是同一个锁2.同步的好处  同步的出现解决了多线程的安全问题3.同步的弊端  当线程较多时,因为每个线程都会去判断同步上的锁,这样是很耗费资源的,会降低程序的运行效率.4.同步方法:  1.就是将同步关键字,synchronized加到方法上,此时的锁对象是this  
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
2年前
Python的锁
互斥锁锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,lLock()创建一个锁,初始状态是未锁定当你需要访问该资源时,调用l.acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用l.release方法释放锁!(https:
Wesley13 Wesley13
2年前
Java多线程锁释放
Java多线程运行环境中,在哪些情况下会使对象锁释放?由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的。在以下情况下,持有锁的线程会释放锁:(1)执行完同步代码块,就会释放锁。(synchronized)(2)在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放。(exc