场景1
package com.zj970.lock;
/**
* 标准情况下 是先sendEmail()还是callPhone()?
* 答案: sendEmail()
* 解释: 被synchronized 修饰的方式,锁的对象是方法的调用者
* 所以说这里两个方法调用的对象是同一个,先调用的先执行!
*
* @auther zj970
* @create 2023-04-10 下午4:04
*/
public class LockDemo1 {
public static void main(String[] args) {
Phone1 phone = new Phone1();
new Thread(() -> {
phone.sendEmail();
}, "A").start();
new Thread(() -> {
phone.callOPhone();
}, "B").start();
}
}
class Phone1 {
public synchronized void sendEmail() { System.out.println(Thread.currentThread().getName() + "--->sendEmail");}
public synchronized void callOPhone() {
System.out.println(Thread.currentThread().getName() + "--->callPhone");
}
}
场景2
package com.zj970.lock;
import java.util.concurrent.TimeUnit;
/**
* sendEmail()休眠3秒后 是先执行sendEmail()还是callPhone()
* 答案:sendEmail()
* 解释:被synchronized修饰的方式,锁的对象是方式的调用者
* 所以说这里两个方法调用的对象是同一个,先调用的先执行!
* @auther zj970
* @create 2023-04-10 下午4:15
*/
public class LockDemo2 {
public static void main(String[] args) throws InterruptedException {
Phone2 phone = new Phone2();
new Thread(() -> {
try {
phone.sendEmail();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "A").start();
TimeUnit.SECONDS.sleep(2);
new Thread(() -> {
phone.callOPhone();
}, "B").start();
}
}
class Phone2 {
public synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "--->sendEmail");
}
public synchronized void callOPhone() {
System.out.println(Thread.currentThread().getName() + "--->callPhone");
}
}
场景3
package com.zj970.lock;
import java.util.concurrent.TimeUnit;
/**
* 被synchronized修饰的方法和普通方法 先执行sendEmail()还是callPhone()
* 答案:callPhone()
* 解释:新增加的这个方法没有synchronized修饰,不是同步方法,不受锁的影响!
*
* @auther zj970
* @create 2023-04-10 下午4:22
*/
public class LockDemo3 {
public static void main(String[] args) throws InterruptedException {
Phone3 phone = new Phone3();
new Thread(() -> {
try {
phone.sendEmail();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "A").start();
TimeUnit.SECONDS.sleep(2);
new Thread(() -> {
phone.callOPhone();
}, "B").start();
}
}
class Phone3 {
public synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + "--->sendEmail");
}
//没有synchronized、static就是普通方式
public void callOPhone() {
System.out.println(Thread.currentThread().getName() + "--->callPhone");
}
}
场景4
package com.zj970.lock;
import java.util.concurrent.TimeUnit;
/**
* 被synchronized 修饰的不同方法?new两个实例 先执行sendEmail()还是callPhone()
* 答案:先执行callPhone()
* 解释:被synchronized修饰的不同方法,锁的对象是调用者也就是实例对象
* 这里锁的是不同的调用者,所以互不影响
* @auther zj970
* @create 2023-04-10 下午4:29
*/
public class LockDemo4 {
public static void main(String[] args) throws InterruptedException {
Phone4 phone = new Phone4();
Phone4 phone1 = new Phone4();
new Thread(() -> {
try {
phone.sendEmail();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "A").start();
TimeUnit.SECONDS.sleep(2);
new Thread(() -> {
phone1.callOPhone();
}, "B").start();
}
}
class Phone4 {
public synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "--->sendEmail");
}
public synchronized void callOPhone() {
System.out.println(Thread.currentThread().getName() + "--->callPhone");
}
}
场景5
package com.zj970.lock;
import java.util.concurrent.TimeUnit;
/**
* 两个静态同步方法,都被synchronized修饰。先sendEmail()还是callPhone()?
* 答案:sendEmail()
* 解释: 只要方法被static修饰,锁的对象就是class模板对象,这个则全局唯一!
* 所以说这里是同一个锁,并不是因为synchronized这里程序会从上往下依次执行
* @auther zj970
* @create 2023-04-10 下午4:40
*/
public class LockDemo5 {
public static void main(String[] args) throws InterruptedException {
Phone5 phone = new Phone5();
new Thread(() -> {
try {
phone.sendEmail();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "A").start();
TimeUnit.SECONDS.sleep(2);
new Thread(() -> {
phone.callOPhone();
}, "B").start();
}
}
class Phone5 {
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "--->sendEmail");
}
public static synchronized void callOPhone() {
System.out.println(Thread.currentThread().getName() + "--->callPhone");
}
}
场景6
package com.zj970.lock;
import java.util.concurrent.TimeUnit;
/**
* 被synchronized修饰的普通方法和静态方法 是先sendEmail()还是callPhone()?
* 答案:callPhone()
* 解释:只要被static修饰锁的是class模板,而synchronized锁的是调用的对像
* 这两个锁互不影响,按时间先后执行
* @auther zj970
* @create 2023-04-10 下午5:07
*/
public class LockDemo6 {
public static void main(String[] args) throws InterruptedException {
Phone6 phone = new Phone6();
new Thread(() -> {
try {
phone.sendEmail();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "A").start();
TimeUnit.SECONDS.sleep(2);
new Thread(() -> {
phone.callOPhone();
}, "B").start();
}
}
class Phone6 {
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "--->sendEmail");
}
public synchronized void callOPhone() {
System.out.println(Thread.currentThread().getName() + "--->callPhone");
}
}
场景7
package com.zj970.lock;
import java.util.concurrent.TimeUnit;
/**
* 同被static+synchronized修饰的两个方法(两个实例对象),是先sendEmail()还是callPhone()?
* 答案:sendEmail
* 解释:只要方法被static修饰,锁的对象就是class模板对象,这个则全局唯一
* 所以说这里是同一个锁,并不是因为synchronized
* @auther zj970
* @create 2023-04-10 下午5:19
*/
public class LockDemo7{
public static void main(String[] args) throws InterruptedException {
Phone7 phoneA = new Phone7();
Phone7 phoneB = new Phone7();
new Thread(() -> {
try {
phoneA.sendEmail();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "A").start();
TimeUnit.SECONDS.sleep(2);
new Thread(() -> {
phoneB.callOPhone();
}, "B").start();
}
}
class Phone7 {
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "--->sendEmail");
}
public static synchronized void callOPhone() {
System.out.println(Thread.currentThread().getName() + "--->callPhone");
}
}
场景8
package com.zj970.lock;
import java.util.concurrent.TimeUnit;
/**
* 一个被static+synchronized修饰的方法和普通的synchronized方法,先执行sendEmail还是callPhone?
* 答案:callPhone()
* 解释:只要被static修饰的锁就是整个class模板
* 这里一个锁的是class模板,一个锁的是拥有者
* 所以锁的是两个对象,互不影响
*
* @auther zj970
* @create 2023-04-10 下午5:40
*/
public class LockDemo8 {
public static void main(String[] args) throws InterruptedException {
Phone8 phone = new Phone8();
Phone8 phone1 = new Phone8();
new Thread(() -> {
try {
phone.sendEmail();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "A").start();
TimeUnit.SECONDS.sleep(2);
new Thread(() -> {
phone1.callOPhone();
}, "B").start();
}
}
class Phone8 {
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "--->sendEmail");
}
public synchronized void callOPhone() {
System.out.println(Thread.currentThread().getName() + "--->callPhone");
}
}
总结
只要分析锁的对象是那个就可以,staic + synchronized 锁的class全局唯一模板。单独synchronized修饰锁的是调用者(也就是实例化出来的对象,这个不唯一),调用者是同一对象,则按照锁的流程走。没有修饰的不受锁的影响。
- 参考博客