Skip to content
DAILY QUOTE

“ ”

8锁,就是关于锁的8个问题

  • 1、标准情况下,两个线程先打印 发短信 还是 打电话? ==1/发短信 2/打电话==
java
package com.mystpet.Test;  
  
import java.sql.Time;  
import java.util.concurrent.TimeUnit;  
  
/*synchronized锁的是方法的调用者  
* 两个方法用的同一个锁,谁先拿到谁执行*/  
  
public class test1 {  
    public static void main(String[] args) {  
        Phone phone=new Phone();  
  
        new Thread(()->{  
            phone.sendSms();  
        },"A").start();  
  
//        try {  
//            TimeUnit.SECONDS.sleep(1);  
//        } catch (InterruptedException e) {  
//            throw new RuntimeException(e);  
//        }  
  
        new Thread(()->{  
            phone.call();  
        },"B").start();  
    }  
}  
class Phone{  
    public synchronized void sendSms(){  
//        try {  
//            TimeUnit.SECONDS.sleep(4);  
//        } catch (InterruptedException e) {  
//            throw new RuntimeException(e);  
//        }  
        System.out.println("发短信");  
    }  
    public synchronized void call(){  
        System.out.println("打电话");  
    }  
}
  • 2、sendSms延迟4秒,两个线程先打印 发短信 还是 打电话? ==1/发短信 2/打电话==
java
package com.mystpet.Test;  
  
import java.sql.Time;  
import java.util.concurrent.TimeUnit;  
  
/*synchronized锁的是方法的调用者  
* 两个方法用的同一个锁,谁先拿到谁执行*/  

//锁在sendSms方法中,跟着延迟4s
  
public class test1 {  
    public static void main(String[] args) {  
        Phone phone=new Phone();  
  
        new Thread(()->{  
            phone.sendSms();  
        },"A").start();  
  

  
        new Thread(()->{  
            phone.call();  
        },"B").start();  
    }  
}  
class Phone{  
    public synchronized void sendSms(){  
        try {  
            TimeUnit.SECONDS.sleep(4);  
        } catch (InterruptedException e) {  
            throw new RuntimeException(e);  
        }  
        System.out.println("发短信");  
    }  
    public synchronized void call(){  
        System.out.println("打电话");  
    }  
}
  • 3、增加了一个普通方法!先执行 发短信 还是 hello? ==1/hello(普通方法) 2/发短信==
java
package com.mystpet.Test;  
  
import java.util.concurrent.TimeUnit;  
  
public class Test2 {  
    public static void main(String[] args) {  
        Phone2 phone2=new Phone2();  
        new Thread(()->{  
            phone2.sendSms();  
        },"A").start();  
  
        new Thread(()->{  
            phone2.hello();  
        },"B").start();  
    }  
}  
class Phone2{  
    public synchronized void sendSms(){  
        try {  
            TimeUnit.SECONDS.sleep(4);  
        } catch (InterruptedException e) {  
            throw new RuntimeException(e);  
        }  
        System.out.println("发短信");  
    }  
    public synchronized void call(){  
  
        System.out.println("打电话");  
    }  
  
    // 这里没有锁!不是同步方法,不受锁的影响  
    public void hello(){  
        System.out.println("hello");  
    }  
}
  • 4、两个对象、两个同步方法,先执行 发短信 还是 打电话? ==1/打电话 2/发短信==
java
package com.mystpet.Test;  
  
import java.util.concurrent.TimeUnit;  
  
/*  
phone1与phone2为两个对象,锁的是对象的调用者,两个对象两把锁,互不影响  
*/  
  
  
public class Test2 {  
    public static void main(String[] args) {  
        Phone2 phone2=new Phone2();  
        Phone2 phone1=new Phone2();  
        new Thread(()->{  
            phone1.sendSms();  
        },"A").start();  
  
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            throw new RuntimeException(e);  
        }  
  
        new Thread(()->{  
            phone2.call();  
        },"B").start();  
    }  
}  
class Phone2{  
    public synchronized void sendSms(){  
        try {  
            TimeUnit.SECONDS.sleep(4);  
        } catch (InterruptedException e) {  
            throw new RuntimeException(e);  
        }  
        System.out.println("发短信");  
    }  
    public synchronized void call(){  
  
        System.out.println("打电话");  
    }  
  
    // 这里没有锁!不是同步方法,不受锁的影响  
    public void hello(){  
        System.out.println("hello");  
    }  
}
  • 5、增加两个静态的同步方法,只有一个对象,先打印 发短信 还是 打电话? ==1/发短信 2/打电话 (锁的是Class)==
java
package com.mystpet.Test;  
  
import java.util.concurrent.TimeUnit;  
  
public class Test3 {  
    public static void main(String[] args) {  
        // 两个对象的class类模板只有一个,static  
        Phone3 phone1 = new Phone3();  
        Phone3 phone2 = new Phone3();  
  
        // 有锁的存在  
        new Thread(() -> {  
            phone1.sendSms();  
        }, "A").start();  
  
        // 捕获  
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
  
        new Thread(() -> {  
            phone2.call();  
        }, "B").start();  
    }  
}  
class Phone3 {  
  
    // synchronized 锁的对象是方法的调用者!  
    // static 静态方法  
    // 类一加载就有了!锁的是Class  
    public static synchronized void sendSms() {  
        try {  
            TimeUnit.SECONDS.sleep(4);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("发短信");  
    }  
  
    public static synchronized void call() {  
        System.out.println("打电话");  
    }  
  
}
  • 6、两个对象!增加两个静态的同步方法,只有一个对象,先打印 发短信 还是 打电话? ==1/发短信 2/打电话 (锁的还是Class)==
java
package com.mystpet.Test;  
  
import java.util.concurrent.TimeUnit;  
  
/*  
锁的是模板,也就是class,所以不同对象依然调用同一个锁  
*/  
  
  
public class Test3 {  
    public static void main(String[] args) {  
        // 两个对象的class类模板只有一个,static  
        Phone3 phone1 = new Phone3();  
        Phone3 phone2 = new Phone3();  
  
        // 有锁的存在  
        new Thread(() -> {  
            phone1.sendSms();  
        }, "A").start();  
  
        // 捕获  
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
  
        new Thread(() -> {  
            phone2.call();  
        }, "B").start();  
    }  
}  
class Phone3 {  
  
    // synchronized 锁的对象是方法的调用者!  
    // static 静态方法  
    // 类一加载就有了!锁的是Class  
    public static synchronized void sendSms() {  
        try {  
            TimeUnit.SECONDS.sleep(4);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("发短信");  
    }  
  
    public static synchronized void call() {  
        System.out.println("打电话");  
    }  
  
}
  • 7、一个静态同步方法,一个普通同步方法,只有一个对象,先打印 发短信 还是 打电话? ==1/打电话 2/发短信==
java
package com.mystpet.Test;  
  
import java.util.concurrent.TimeUnit;  
  
/*  
类锁与调用锁互不影响,平行进行  
*/  
  
public class Test4 {  
    public static void main(String[] args) {  
        Phone4 phone1 = new Phone4();  
  
        new Thread(() -> {  
            phone1.sendSms();  
        }, "A").start();  
  
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
  
        new Thread(() -> {  
            phone1.call();  
        }, "B").start();  
    }  
}  
  
class Phone4 {  
  
    // 静态同步方法 锁的是Class类模板  
    public static synchronized void sendSms() {  
        try {  
            TimeUnit.SECONDS.sleep(4);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("发短信");  
    }  
  
    // 普通同步方法 锁的是调用者  
    public synchronized void call() {  
        System.out.println("打电话");  
    }  
  
}
  • 8、一个静态同步方法,一个普通同步方法,两个对象,先打印 发短信 还是 打电话? ==1/打电话 2/发短信==
java
package com.mystpet.Test;  
  
import java.util.concurrent.TimeUnit;  
  
/*  
类锁只锁static方法,调用锁只锁普通同步方法,两者不影响  
*/  
  
public class Test4 {  
    public static void main(String[] args) {  
        Phone4 phone1 = new Phone4();  
        Phone4 phone2 = new Phone4();  
  
        new Thread(() -> {  
            phone1.sendSms();  
        }, "A").start();  
  
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
  
        new Thread(() -> {  
            phone2.call();  
        }, "B").start();  
    }  
}  
  
class Phone4 {  
  
    // 静态同步方法 锁的是Class类模板  
    public static synchronized void sendSms() {  
        try {  
            TimeUnit.SECONDS.sleep(4);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("发短信");  
    }  
  
    // 普通同步方法 锁的是调用者  
    public synchronized void call() {  
        System.out.println("打电话");  
    }  
  
}

小结

  • new this 具体的一个手机
  • static Class 唯一的一个模板