3.八锁现象

问题一,二

//1.标准情况下,两个线程先打印发短信还是打电话 1/send 2/call-----》send
//2.send延迟4秒,两个线程先打印发短信还是打电话 1/send 2/call-----》先等4秒再send
//回答:因为有锁的存在,synchronized锁的对象是方法的调用者,因为再这个方法中对象只有一个phone,
// 也就是同一把锁,所以谁先拿到锁谁就先执行
public class Test1 {
    public static void main(String[] args) {
        Phone phone=new Phone();
        new Thread(()->{phone.send();},"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        new Thread(()->{phone.call();},"B").start();
    }
}
class Phone{
    public synchronized void send(){
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("send");
    }
    public synchronized void call(){
        System.out.println("call");
    }
}

问题三

//3.如下两个线程是打印send(synchronized方法)还是hello(普通方法)--》1s后打印hello 4s后打印了send
//回答,hello没有锁不受锁的影响
public class Test2 {
    public static void main(String[] args) {
        Phone2 phone=new Phone2();
        new Thread(()->{phone.send();},"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        new Thread(()->{phone.hello();},"B").start();
    }
}

class Phone2{
    public synchronized void send(){
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("send");
    }
    public void hello(){
        System.out.println("hello");
    }
}

问题四:

//4.两个对象,两个同步方法,先send还是先call --》先call因为send睡眠了4s
//回答,hello没有锁不受锁的影响
public class Test2 {
    public static void main(String[] args) {
        Phone2 phone1=new Phone2();
        Phone2 phone2=new Phone2();
        new Thread(()->{phone1.send();},"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        new Thread(()->{phone2.call();},"B").start();
    }
}

class Phone2{
    public synchronized void send(){
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("send");
    }
    public synchronized void call(){
        System.out.println("call");
    }
}

问题五,六

//5.现在是一个对象,但是两个方法都变成了静态方法先send还是先call? 等4秒先send后call
//6. 如果现在是两个对象,两个静态方法,先send还是先call? 等4秒先send后call
//回答,于之前的情况来说对于静态方法,他的锁不是对象而是Class,只有唯一的一个class对象,与对象其实已经无关了

public class Test3 {
    public static void main(String[] args) {
        Phone3 phone1=new Phone3();
        Phone3 phone2=new Phone3();
        new Thread(()->{phone1.send();},"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        new Thread(()->{phone2.call();},"B").start();
    }
}

class Phone3{
    public static synchronized void send(){
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("send");
    }
    public static synchronized void call(){
        System.out.println("call");
    }
}

 问题七,八(两个对象也是打电话,两把锁是一个class模板一个对象和两个对象无关)

//对于一个普通同步方法call和一个静态同步方法send,只使用一个对象来调用,先send还是先call?
// 先call,再send。两个方法使用的是两把锁,call不需要等待所以比send快
public class Test4 {
    public static void main(String[] args) {
        Phone4 phone1=new Phone4();
        new Thread(()->{phone1.send();},"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        new Thread(()->{phone1.call();},"B").start();
    }
}

class Phone4{
    public static synchronized void send(){
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("send");
    }
    public synchronized void call(){
        System.out.println("call");
    }
}

 

上一篇:c++使用map保存成员函数地址


下一篇:JDK动态代理和CGLIB动态代理