2022.8.21 8锁的现象
5、8锁的现象
如何判断锁的是谁,锁到底锁的是谁:对象和class
Test1
package com.xing.lock8;
import java.util.concurrent.TimeUnit;
/**
* 8锁,就是关于锁的八个问题
* 1.标准情况下,两个线程去打印 先输出发短息还是打电话? 输出结果 1、发短信 2、打电话
* 1.sendSms延迟四秒,四个线先打印 先输出发短信还是打电话 输出结果 1、发短信 2、打电话
*/
public class Test1 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
phone.sendSms();
},"A").start();
//休息一秒
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone.call();
}, "B").start();
}
}
class Phone {
//synchronized 锁的对象是方法的调用者! 所以两个方法用的是phone的锁,每个对象只有一把锁,谁先拿到谁执行
public synchronized void sendSms() {
/* try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
e.printStackTrace();
}*/
System.out.println("发信息");
}
public synchronized void call() {
System.out.println("打电话");
}
}
Test2
package com.xing.lock8;
import java.util.concurrent.TimeUnit;
/**
* 增加了一个普通方法并且把call换成普通方法(Hello) 先输出发短信还是hello 输出结果 1、hello 2、发短信 因为hello()是一个普通方法
*/
public class Test2{
public static void main(String[] args) throws InterruptedException {
Phone2 phone = new Phone2();
new Thread(()->{
phone.sendSms();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone.Hello();
}, "B").start();
}
}
class Phone2 {
//synchronized 锁的对象是方法的调用者!
public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发信息");
}
public synchronized void call() {
System.out.println("打电话");
}
// 这里没有锁 不是同步方法 不受锁的影响
public void Hello() {
System.out.println("hello");
}
}
Test3
package com.xing.lock8;
import java.util.concurrent.TimeUnit;
/**
* 两个对象,两个同步方法, 先输出发短信还是打电话 输出结果 1、打电话 2、发短信
* sendSms 睡了3秒 所以先输出打电话
*
*/
public class Test3{
public static void main(String[] args) throws InterruptedException {
//两个不同的对象,两个调用者,两把锁
Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
new Thread(()->{
phone1.sendSms();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone2.call();
}, "B").start();
}
}
class Phone3 {
//synchronized 锁的对象是方法的调用者!
public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发信息");
}
public synchronized void call() {
System.out.println("打电话");
}
}
Test4
package com.xing.lock8;
import java.util.concurrent.TimeUnit;
/**
* 增加两个静态的同步方法,只有一个对象,输出结果 1.发信息 2.打电话
*/
public class Test4 {
public static void main(String[] args) throws InterruptedException {
Phone4 phone = new Phone4();
new Thread(()->{
phone.sendSms();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone.call();
}, "B").start();
}
}
// Phone4只有唯一的class对象 Class<Phone4> class = Phone4.class;
class Phone4 {
//加上static静态方法 : 类一加载就有了,所以锁得是整个Class 两个方法用的同一把锁
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发信息");
}
public static synchronized void call() {
System.out.println("打电话");
}
}
Test5
package com.xing.lock8;
import java.util.concurrent.TimeUnit;
/**
* 增加两个静态的同步方法,只有两个对象,输出结果 1.发信息 2.打电话 原因:static 锁的是整个Class
*/
public class Test5 {
public static void main(String[] args) throws InterruptedException {
// 两个对象的Class对象模板只有一个 锁的是Class
Phone5 phone1 = new Phone5();
Phone5 phone2 = new Phone5();
new Thread(()->{
phone1.sendSms();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone2.call();
}, "B").start();
}
}
class Phone5 {
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发信息");
}
public static synchronized void call() {
System.out.println("打电话");
}
}
Test6
package com.xing.lock8;
import java.util.concurrent.TimeUnit;
/**
* 1个静态的同步方法和一个普通的同步方法,一个对象 ,输出结果 1.打电话 ,发短信
*/
public class Test6 {
public static void main(String[] args) throws InterruptedException {
Phone6 phone = new Phone6();
new Thread(()->{
phone.sendSms();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone.call();
}, "B").start();
}
}
class Phone6 {
// 静态同步方法 锁的是Class
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发信息");
}
// 普通同步方法 锁的是对象phone 不需要等待sendSms(),因为两个方法用的不是用一把锁 sendSms()睡了3秒
public synchronized void call() {
System.out.println("打电话");
}
}
Test7
package com.xing.lock8;
import java.util.concurrent.TimeUnit;
/**
* 1个静态的同步方法和一个普通的同步方法,两个对象 ,输出结果 1.打电话 ,发短信
*/
public class Test7 {
public static void main(String[] args) throws InterruptedException {
//两个对象的Class类模板只有一个
Phone7 phone1 = new Phone7();
Phone7 phone2 = new Phone7();
new Thread(()->{
phone1.sendSms();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone2.call();
}, "B").start();
}
}
class Phone7 {
// 静态同步方法 锁的是Class
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发信息");
}
// 普通同步方法 锁的是对象phone 因为两个方法用的不是用一把锁 sendSms()睡了3秒
public synchronized void call() {
System.out.println("打电话");
}
}
全面总结:
-
普通带锁方法:锁对象,同一对象下的才按顺序执行,如果是同一个类下的不同对象则不受影响。
-
普通不带锁方法:不受任何影响。
-
静态带锁方法:锁类,同一个类下的所有对象的所有带锁方法都得按顺序执行。
-
小结:
-
new this 具体的一个对象
-
static Class 唯一的模板
-