八锁现象
1、标准访问,请问先打印邮件还是短信?
package com.dakuzai.lock8;
import java.util.concurrent.TimeUnit;
/**
* **1、标准访问,请问先打印邮件1还是短信2?**
*
*
*/
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
// 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
new Thread(() -> {
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone.sendMS();
}, "B").start();
}
}
// 手机,发短信,发邮件
class Phone {
// 被 synchronized 修饰的方法、锁的对象是方法的调用者、
public synchronized void sendEmail() {
System.out.println("sendEmail");
}
public synchronized void sendMS() {
System.out.println("sendMS");
}
}
2、邮件方法暂停4秒钟,请问先打印邮件还是短信?
package com.dakuzai.lock8;
import java.util.concurrent.TimeUnit;
/**
* **2、邮件方法暂停4秒钟,请问先打印邮件还是短信?**
*/
public class Test2 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
// 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
new Thread(() -> {
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone.sendMS();
}, "B").start();
}
}
// 手机,发短信,发邮件
class Phone2 {
// 被 synchronized 修饰的方法、锁的对象是方法的调用者、
public synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public synchronized void sendMS() {
System.out.println("sendMS");
}
}
3、新增一个普通方法hello()没有同步,请问先打印邮件还是hello?
package com.dakuzai.lock8;
import java.util.concurrent.TimeUnit;
/**
* 3、新增一个普通方法hello()没有同步,请问先打印邮件还是hello?
*/
public class Test3 {
// 回家 卧室(锁) 厕所
public static void main(String[] args) {
Phone3 phone = new Phone3();
// 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone.hello();
}, "B").start();
}
}
// 锁:竞争机制
// 手机,发短信,发邮件
class Phone3 {
// 被 synchronized 修饰的方法、锁的对象是方法的调用者、
public synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public synchronized void sendMS() {
System.out.println("sendMS");
}
// 新增的方法没有被 synchronized 修饰,不是同步方法,所以不需要等待,其他线程用了一个把锁
public void hello() {
System.out.println("hello");
}
}
4、两部手机、请问先打印邮件还是短信?
package com.dakuzai.lock8;
import java.util.concurrent.TimeUnit;
/**
* **4、两部手机、请问先打印邮件还是短信?**
*/
public class Test4 {
// 回家 卧室(锁) 厕所
public static void main(String[] args) {
// 两个对象,互不干预
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
// 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
new Thread(() -> { // 一开始就执行了
phone1.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone2.sendMS();
}, "B").start();
}
}
// 手机,发短信,发邮件
class Phone4 {
// 被 synchronized 修饰的方法、锁的对象是方法的调用者、调用者不同,没有关系,两个方法用得不是同一个锁!
public synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public synchronized void sendMS() {
System.out.println("sendMS");
}
}
5、两个静态同步方法,同一部手机,请问先打印邮件还是短信?
package com.dakuzai.lock8;
import java.util.concurrent.TimeUnit;
/*
**5、两个静态同步方法,同一部手机,请问先打印邮件还是短信?**
*/
public class Test5 {
// 回家 卧室(锁) 厕所
public static void main(String[] args) {
// 两个对象,互不干预
Phone5 phone = new Phone5();
// 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone.sendMS();
}, "B").start();
}
}
// 手机,发短信,发邮件
class Phone5 {
// 对象 类模板可以new 多个对象!
// Class 类模版,只有一个
// 被 synchronized 修饰 和 static 修饰的方法,锁的对象是类的 class 对象!唯一的
// 同一把锁
public static synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public static synchronized void sendMS() {
System.out.println("sendMS");
}
}
6、两个静态同步方法,2部手机,请问先打印邮件还是短信?
package com.dakuzai.lock8;
import java.util.concurrent.TimeUnit;
/** 第一次听可能不会,第二次也可能不会,但是不要放弃,你可以!
**6、两个静态同步方法,2部手机,请问先打印邮件还是短信?**
*/
public class Test6 {
// 回家 卧室(锁) 厕所
public static void main(String[] args) {
// 两个对象,互不干预
Phone5 phone = new Phone5();
Phone5 phone2 = new Phone5();
// 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone2.sendMS();
}, "B").start();
}
}
// 手机,发短信,发邮件
class Phone6 {
// 对象 类模板可以new 多个对象!
// Class 类模版,只有一个
// 被 synchronized 修饰 和 static 修饰的方法,锁的对象是类的 class 对象!唯一的
// 同一把锁
public static synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public static synchronized void sendMS() {
System.out.println("sendMS");
}
}
7、一个普通同步方法,一个静态同步方法,同一部手机,请问先打印邮件还是短信?
package com.dakuzai.lock8;
import java.util.concurrent.TimeUnit;
/**
* 7、一个普通同步方法,一个静态同步方法,同一部手机,请问先打印邮件还是短信?**
*/
public class Test7 {
// 回家 卧室(锁) 厕所
public static void main(String[] args) {
// 两个对象,互不干预
Phone7 phone = new Phone7();
// 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone.sendMS();
}, "B").start();
}
}
class Phone7{
// CLASS
public static synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
// 对象
// 普通同步方法
public synchronized void sendMS() {
System.out.println("sendMS");
}
}
8、一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信?
package com.dakuzai.lock8;
import java.util.concurrent.TimeUnit;
/**
* **8、一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信?**
*/
public class Test8 {
public static void main(String[] args) {
// 两个对象,互不干预
Phone8 phone = new Phone8();
Phone8 phone2 = new Phone8();
// 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone2.sendMS();
}, "B").start();
}
}
class Phone8{
// CLASS
public static synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
// 对象
// 普通同步方法
public synchronized void sendMS() {
System.out.println("sendMS");
}
}
小结
new this 本身的这个对象,调用者
static class 类模板,保证唯一!
-
一个对象中有多个 synchronized 方法,某个时刻内只要有一个线程去访问 synchronized 方法了就会被加锁,其他线程就会阻塞!
-
加了一个普通方法后 ,两个对象,无关先后,一个有锁,一个没锁!情况会变化!
-
换成静态同步方法,情况会变化! CLASS ,所有静态同步方法的锁唯一 对象实例class 本身!