锁的8个现象我写了4个测试类,每个测试类里两个现象都是相似的!!!
/**
* 8锁现象
* 1.先发短信还是先打电话? 答:先发短信,再打电话,因为synchronized 锁的对象是方法的调用者,谁先执行谁先输出
* 2.在发短信方法中加4秒延时,看先发短信还是先打电话? 答:还是先发短信,再打电话,因为synchronized 锁的对象是方法的调用者,谁先执行谁先输出,即使发短信方法卡着4秒但是锁还没有被释放
*
*/
public class TestLock1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(() -> phone.sendSms(), "A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> phone.call(), "B").start();
}
}
class Phone {
//synchronized 锁的对象是方法的调用者
//两个方法是一个调用者,谁先拿到谁先执行
public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call() {
System.out.println("打电话");
}
}
/**
* 8锁现象
* 3.加一个普通方法,然后调用,看先发短信还是先输出hello? 答:先输出普通方法hello,在输出发短信
* 4.两个对象,调用不同的同步方法,先发短信还是先打电话? 答:先打电话,再发短信,因为发短信有延时在阻塞,如果没有阻塞则不一定,哪个对象先抢占到cpu谁先执行
*/
public class TestLock2 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
Phone2 phone1 = new Phone2();
new Thread(() -> phone.sendSms(), "A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// new Thread(() -> phone.hello(),"B").start();
new Thread(() -> phone1.call(), "B").start();
}
}
class Phone2 {
//synchronized 锁的对象是方法的调用者
public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call() {
System.out.println("打电话");
}
//这个方法没有锁,所以不受锁的影响
public void hello() {
System.out.println("hello");
}
}
/**
* 8锁现象
* 5.给打电话和发短信加上static关键字,同一个对象再进行调用是先发短信还是先打电话? 答:是先发短信,在打电话,因为两个同步方法都被static修饰,
* 被static修饰后锁的是类,而非对象,类是全局唯一的所以先调用的发短信在调用的打电话方法,输出的就是先发短信再打电话
* 6.给打电话和发短信加上static关键字,两个对象进行调用,一个调用发短信,一个调用打电话,是先发短信还是先打电话? 答:先发短信,因为两个同步方法都被static修饰过,
* 就算是两个对象调用不同的方法,但是被static修饰过的同步方法锁的是同一个Class类模板,所以先调用的发短信在调用的打电话方法,输出的就是先发短信再打电话
*/
public class TestLock3 {
public static void main(String[] args) {
//两个对象的Class类模板只有一个,static,锁的是Class
Phone3 phone = new Phone3();
Phone3 phone1 = new Phone3();
new Thread(() -> phone.sendSms(), "A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> phone1.call(), "B").start();
}
}
//全局唯一的Class
class Phone3 {
//synchronized 锁的对象是方法的调用者,而被static修饰过的方法为静态方法,类一加载就有了,所以锁的是Class
//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("打电话");
}
}
/**
* 8锁现象
* 7.一个静态的同步方法,一个普通的同步方法,一个对象调用,是先发短信还是先打电话? 答:先打电话,因为static修饰的同步方法锁的是Class的类模板,
* 而普通同步方法锁的是对象,两个不是一个锁,自然是执行快的先输出
* 8.一个静态的同步方法,一个普通的同步方法,两个对象调用,是先发短信还是先打电话? 答:先打电话,因为static修饰的同步方法锁的是Class的类模板,
* 而普通同步方法锁的是对象,两个不是一个锁并且不是同一个对象,自然是执行快的先输出
*/
public class TestLock4 {
public static void main(String[] args) {
Phone4 phone = new Phone4();
Phone4 phone1 = new Phone4();
new Thread(() -> phone.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("打电话");
}
}
如果有感觉不妥的地方请私信我!!!