java的8锁问题

正经学徒,佛系记录,不搞事情

8锁即8个关于锁执行顺序的问题

解决问题前,首先需要明白的是 synchronized 只会锁两样东西,一样是调用的对象,一样是Class

问题一:两个普通的锁方法,new一个对象调用,调用过程中间睡1秒,执行结果是什么

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Fun fun = new Fun();
        new Thread(()->{fun.funOne();},"A线程").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{fun.funTwo();},"B线程").start();
    }
}

class Fun{
    public synchronized void funOne(){
        System.out.println(Thread.currentThread().getName()+":调用方法一");
    }
    public synchronized void funTwo(){
        System.out.println(Thread.currentThread().getName()+":调用方法二");
    }
}

判断执行顺序,先判断什么被锁了,这里synchronized锁的是Fun对象new出来的fun,因为先调用了funOne睡1秒后调用的funTwo,funTwo需要等到funOne释放锁后才会执行

最终执行结果是:A线程:调用方法一   B线程:调用方法二

问题二:两个普通的锁方法,new一个对象调用,调用过程中间睡1秒,且在funOne方法中睡3秒,执行结果是什么

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Fun fun = new Fun();
        new Thread(()->{
            try {  fun.funOne();  } catch (InterruptedException e) {  e.printStackTrace();  }
        },"A线程").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{fun.funTwo();},"B线程").start();
    }
}

class Fun{
    public synchronized void funOne() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName()+":调用方法一");
    }
    public synchronized void funTwo(){
        System.out.println(Thread.currentThread().getName()+":调用方法二");
    }
}

该情况其实和问题一 一样,synchronized锁的是Fun对象new出来的fun,当调用funOne时,fun被锁,而程序不受funOne内睡的影响继续执行,在调用funTwo的时候因为fun被锁导致等待,当funOne执行完后funTwo瞬间执行

最终执行结果是:3 秒后同时出现 A线程:调用方法一   B线程:调用方法二

问题三:一个普通的锁方法,一个普通无锁方法,new一个对象调用,在funOne方法中睡3秒,执行结果是什么

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Fun fun = new Fun();
        new Thread(()->{
            try {  fun.funOne();  } catch (InterruptedException e) {  e.printStackTrace();  }
        },"A线程").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{fun.funTwo();},"B线程").start();
    }
}

class Fun{
    public synchronized void funOne() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName()+":调用方法一");
    }
    public void funTwo(){
        System.out.println(Thread.currentThread().getName()+":调用方法二");
    }
}

程序执行在funOne中锁了fun并在方法中睡3秒,外部在睡1秒后调用funTwo,因为无锁因此直接执行

最终执行结果是:1 秒后出现B线程:调用方法二 再2秒后出现 A线程:调用方法一  

问题四:两个普通的锁方法,new两个对象分别调用,在funOne方法中睡3秒,执行结果是什么

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Fun fun1 = new Fun();
        Fun fun2 = new Fun();
        new Thread(()->{
            try {  fun1.funOne();  } catch (InterruptedException e) {  e.printStackTrace();  }
        },"A线程").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{fun2.funTwo();},"B线程").start();
    }
}

class Fun{
    public synchronized void funOne() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName()+":调用方法一");
    }
    public synchronized void funTwo(){
        System.out.println(Thread.currentThread().getName()+":调用方法二");
    }
}

程序调用funOne时锁住fun1,外部睡1秒后调用funTwo时锁funTwo,互不影响

最终执行结果是:B线程:调用方法二   A线程:调用方法一

问题五:两个静态的锁方法,new一个对象调用,在funOne方法中睡3秒,执行结果是什么

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Fun fun = new Fun();
        new Thread(()->{
            try {  fun.funOne();  } catch (InterruptedException e) {  e.printStackTrace();  }
        },"A线程").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{fun.funTwo();},"B线程").start();
    }
}

class Fun{
    public static synchronized void funOne() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName()+":调用方法一");
    }
    public static synchronized void funTwo(){
        System.out.println(Thread.currentThread().getName()+":调用方法二");
    }
}

这里多了静态static,因此此时锁的东西改变了,funOne和funTwo都是锁的Fun这个class,程序在执行funOne时锁住Fun class,睡1秒后调用funTwo,funTwo等待funOne内睡完释放锁后再执行

最终执行结果是:A线程:调用方法一   B线程:调用方法二

问题六:两个静态的锁方法,new两个对象分别调用,在funOne方法中睡3秒,执行结果是什么

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Fun fun1 = new Fun();
        Fun fun2 = new Fun();
        new Thread(()->{
            try {  fun1.funOne();  } catch (InterruptedException e) {  e.printStackTrace();  }
        },"A线程").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{fun2.funTwo();},"B线程").start();
    }
}

class Fun{
    public static synchronized void funOne() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName()+":调用方法一");
    }
    public static synchronized void funTwo(){
        System.out.println(Thread.currentThread().getName()+":调用方法二");
    }
}

要注意的是,不管现在new结果对象,调用方法后锁的都是Fun class,funTwo会被funOne阻塞

最终执行结果是:A线程:调用方法一   B线程:调用方法二

问题七:一个静态的锁方法,一个普通锁方法,new一个对象调用,在funOne方法中睡3秒,执行结果是什么

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Fun fun = new Fun();
        new Thread(()->{
            try {  fun.funOne();  } catch (InterruptedException e) {  e.printStackTrace();  }
        },"A线程").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{fun.funTwo();},"B线程").start();
    }
}

class Fun{
    public static synchronized void funOne() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName()+":调用方法一");
    }
    public synchronized void funTwo(){
        System.out.println(Thread.currentThread().getName()+":调用方法二");
    }
}

同样只要确认锁的是不是一个东西就知道会不会阻塞,调用funOne时阻塞的是Fun class,调用funTwo时阻塞的是fun

最终执行结果是:B线程:调用方法二   A线程:调用方法一

问题八:一个静态的锁方法,一个普通锁方法,new两个对象分别调用,在funOne方法中睡3秒,执行结果是什么

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Fun fun1 = new Fun();
        Fun fun2 = new Fun();
        new Thread(()->{
            try {  fun1.funOne();  } catch (InterruptedException e) {  e.printStackTrace();  }
        },"A线程").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{fun2.funTwo();},"B线程").start();
    }
}

class Fun{
    public static synchronized void funOne() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName()+":调用方法一");
    }
    public synchronized void funTwo(){
        System.out.println(Thread.currentThread().getName()+":调用方法二");
    }
}

解题跟问题七一致,调用funOne时阻塞的是Fun class,调用funTwo时阻塞的是fun2

最终执行结果是:B线程:调用方法二   A线程:调用方法一

  • 16
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

My name is Red ^^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值