synchronized面试题

  • 分析以下四个程序:判断t2线程是否需要等待t1线程执行完毕再执行?

(1)

package com.dh.threadsafe3;

public class SynchronizedTest {
    public static void main(String[] args) {
        Do d = new Do();
        Thread t1 = new MyThread(d);
        Thread t2 = new MyThread(d);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        try {
            Thread.sleep(1000); //保证t1线程先执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}

class MyThread extends Thread {
    private Do d;
    public MyThread(Do d) {
        this.d = d;
    }

    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("t1")){
            d.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")){
            d.doOther();
        }
    }
}

class Do{
    //锁的是this对象
    public synchronized void doSome(){
        System.out.println("doSome begin");
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("doSome over");
    }
    public void doOther(){
        System.out.println("doOther begin");
        System.out.println("doOther over");
    }
}

此时t2线程是否需要等待t1线程先执行完毕?

不需要,虽然线程t1和线程t2共享this,但是因为t2线程不需要共享资源的锁,所以不需要等待t1线程执行完毕归还锁。

结果:

doSome begin
doOther begin
doOther over
doSome over

所以doOther()会先执行完毕。

(2)

(其余代码不变)

public synchronized void doOther(){
    System.out.println("doOther begin");
    System.out.println("doOther over");
}

此时因为t1线程和t2线程需要的是同一把对象的锁(this,即d),所以t2线程需要等先拿到锁的t1线程执行完毕归还锁之后,再拿到锁后执行代码。

结果:

doSome begin
doSome over
doOther begin
doOther over

(3)

package com.dh.threadsafe3;

public class SynchronizedTest {
    public static void main(String[] args) {
        Do d = new Do();
        Thread t1 = new MyThread(d);
        Do d2 = new Do();
        Thread t2 = new MyThread(d2);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        try {
            Thread.sleep(1000); //保证t1线程先执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}

class MyThread extends Thread {
    private Do d;
    public MyThread(Do d) {
        this.d = d;
    }

    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("t1")){
            d.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")){
            d.doOther();
        }
    }
}

class Do{
    public synchronized void doSome(){
        System.out.println("doSome begin");
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("doSome over");
    }
    public synchronized void doOther(){
        System.out.println("doOther begin");
        System.out.println("doOther over");
    }
}

因为此时的this对象不一样了,t1线程的this是d,而t2线程的this是d2,所以等待的不是同一把锁,t2线程也不需要等待t1线程。

结果:

doSome begin
doOther begin
doOther over
doSome over

(4)

package com.dh.threadsafe3;

public class SynchronizedTest {
    public static void main(String[] args) {
        Do d = new Do();
        Thread t1 = new MyThread(d);
        Do d2 = new Do();
        Thread t2 = new MyThread(d2);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        try {
            Thread.sleep(1000); //保证t1线程先执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}

class MyThread extends Thread {
    private Do d;
    public MyThread(Do d) {
        this.d = d;
    }

    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("t1")){
            d.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")){
            d.doOther();
        }
    }
}

class Do{
    public synchronized static void doSome(){
        System.out.println("doSome begin");
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("doSome over");
    }
    public synchronized static void doOther(){
        System.out.println("doOther begin");
        System.out.println("doOther over");
    }
}

synchronized修饰的是静态方法,所以需要找类锁,虽然是不同的this对象,但是是同一个类Do,所以是线程t1和t2需要的是同一把锁,所以t2线程需要等待t1线程。

结果:

doSome begin
doSome over
doOther begin
doOther over
posted @ 2021-02-23 20:15  deng-hui  阅读(267)  评论(0编辑  收藏  举报