0
点赞
收藏
分享

微信扫一扫

【JUC】002-8锁现象


目录

​​0、警醒自己​​

​​一、问题1和2​​

​​1、问题​​

​​2、代码、注释及运行结果​​

​​代码和注释:​​

​​运行结果:​​

​​3、答案再次说明​​

​​二、问题3​​

​​1、问题​​

​​2、代码、注释及运行结果​​

​​代码和注释:​​

​​运行结果:​​

​​3、答案再次说明​​

​​三、问题4​​

​​1、问题​​

​​2、代码、注释及运行结果​​

​​代码和注释:​​

​​运行结果:​​

​​3、答案再次说明​​

​​四、问题5​​

​​1、问题​​

​​2、代码、注释及运行结果​​

​​代码和注释:​​

​​运行结果:​​

​​3、答案再次说明​​

​​五、问题6​​

​​1、问题​​

​​2、代码、注释及运行结果​​

​​代码及注释:​​

​​运行结果:​​

​​3、答案再次说明​​

​​6、问题7和8​​

​​1、问题​​

​​2、代码、注释及运行结果​​

​​代码及注释:​​

​​运行结果:​​

​​3、答案再次说明​​

0、警醒自己

1、学习不用心,骗人又骗己;

2、学习不刻苦,纸上画老虎;

3、学习不惜时,终得人耻笑;

4、学习不复习,不如不学习;

5、学习不休息,毁眼伤身体;

7、狗才等着别人喂,狼都是自己寻找食物;

 

(问题回顾:什么是锁?到底锁的谁?要么锁new出来的对象,要么是Class,下面详解)

(8锁就是关于锁的8个问题)

一、问题1和2

1、问题

①标准情况下,两个线程是先打印发短信还是打电话?答:先发短信,后打电话;为什么?因为锁,详解见注释;

②让发短信方法睡4秒,是先发短信还是先打电话?答:还是先发短信,后打电话;为什么?因为锁,详解见注释;

 

2、代码、注释及运行结果

代码和注释:

package com.zibo.lock8;

import java.util.concurrent.TimeUnit;

/**
* 8锁:关于锁的8个问题
* 1、标准情况下,两个线程是先打印发短信还是打电话?答:先发短信,后打电话;为什么?因为锁,详解见注释
* 2、让发短信方法睡4秒,是先发短信还是先打电话?答:还是先发短信,后打电话;为什么?因为锁,详解见注释
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
//两个线程,一个发短信,一个打电话
new Thread(phone::sendSms,"A").start();
//中间休息1s
TimeUnit.SECONDS.sleep(1);
new Thread(phone::call,"B").start();
}
}
class Phone{

//synchronized锁的对象是方法的调用者!
//由于方法执行的时候拿到的是同一把锁,所以谁先拿到锁谁先执行
public synchronized void sendSms() throws InterruptedException {
//中间休息4s
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信!");
}

public synchronized void call(){
System.out.println("打电话!");
}
}

运行结果:

发短信!
打电话!

 

3、答案再次说明

synchronized锁的对象是方法的调用者!由于方法执行的时候拿到的是同一把锁,所以谁先拿到锁谁先执行,无论发短信睡了多长时间,发短信没有释放锁,打电话都不会执行;

 

二、问题3

1、问题

A线程调用加了synchronized的发短信方法,B线程调用未加synchronized的hello方法,现在这种情况是先发短信,还是先say hello?

 

2、代码、注释及运行结果

代码和注释:

package com.zibo.lock8;

import java.util.concurrent.TimeUnit;

/**
* 8锁:关于锁的8个问题
* 3、A线程调用加了synchronized的发短信方法,B线程调用未加synchronized的hello方法,现在这种情况是先发短信,还是先say hello?答:先hello
* 4、
*/
public class Test02 {
public static void main(String[] args) throws InterruptedException {
Phone02 phone = new Phone02();
//两个线程,一个发短信,一个打电话
new Thread(() -> {
try {
phone.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
//中间休息1s
TimeUnit.SECONDS.sleep(1);
new Thread(phone::hello,"B").start();
}
}

class Phone02{

//synchronized锁的对象是方法的调用者!
//由于方法执行的时候拿到的是同一把锁,所以谁先拿到锁谁先执行
public synchronized void sendSms() throws InterruptedException {
//中间休息4s
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信!");
}

public synchronized void call(){
System.out.println("打电话!");
}

//答案解析:先hello,因为hello这里没锁,发短信把锁拿走了,不管hello什么事
public void hello(){
System.out.println("say hello!");
}
}

运行结果:

say hello!
发短信!

 

3、答案再次说明

先hello,因为hello这里没锁,发短信把锁拿走了,不管hello什么事;

 

三、问题4

1、问题

使用两个对象,调用发短信和打电话,谁先执行?

 

2、代码、注释及运行结果

代码和注释:

package com.zibo.lock8;

import java.util.concurrent.TimeUnit;

/**
* 8锁:关于锁的8个问题
* 3、A线程调用加了synchronized的发短信方法,B线程调用未加synchronized的hello方法,现在这种情况是先发短信,还是先say hello?答:先hello
* 4、使用两个对象,调用发短信和打电话,谁先执行?答:先打电话,后发短信;
*/
public class Test02 {
public static void main(String[] args) throws InterruptedException {
//使用两个对象,调用发短信和打电话,谁先执行?
Phone02 phone1 = new Phone02();
Phone02 phone2 = new Phone02();
//两个线程,一个发短信,一个打电话
new Thread(() -> {
try {
phone1.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
//中间休息1s
TimeUnit.SECONDS.sleep(1);
new Thread(phone2::call,"B").start();
}
}

class Phone02{

//synchronized锁的对象是方法的调用者!
//由于方法执行的时候拿到的是同一把锁,所以谁先拿到锁谁先执行
public synchronized void sendSms() throws InterruptedException {
//中间休息4s
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信!");
}

//使用两个对象,谁先执行?答:先打电话,后发短信;
//因为不同的锁,锁的是不同的对象,相互没有关系,这个时候就看先执行到到哪句打印语句了
//发短信睡了4秒,显然先执行到打电话
public synchronized void call(){
System.out.println("打电话!");
}

//答案解析:先hello,因为hello这里没锁,发短信把锁拿走了,不管hello什么事
public void hello(){
System.out.println("say hello!");
}
}

运行结果:

打电话!
发短信!

 

3、答案再次说明

使用两个对象,谁先执行?答:先打电话,后发短信;
因为不同的锁对象,相互没有关系,这个时候就看先执行到到哪句打印语句了,发短信睡了4秒,显然先执行到打电话;

 

四、问题5

1、问题

增加两个静态的同步方法,是先发短信还是先打电话?

 

2、代码、注释及运行结果

代码和注释:

package com.zibo.lock8;

import java.util.concurrent.TimeUnit;

/**
* 8锁:关于锁的8个问题
* 5、增加两个静态的同步方法,是先发短信还是先打电话?答:先发短信
*/
public class Test03 {
public static void main(String[] args) throws InterruptedException {
//两个线程,一个发短信,一个打电话
new Thread(() -> {
try {
Phone03.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
//中间休息1s
TimeUnit.SECONDS.sleep(1);
new Thread(Phone03::call,"B").start();
}
}

class Phone03{

//synchronized锁的对象是方法的调用者!静态方法锁的是类
//static方法,类已加载就有了,锁的是class类文件,Phone03只有唯一的一个class类文件
//由于方法执行的时候拿到的是同一把锁,所以谁先拿到锁谁先执行
//Class<Phone03> phone03Class = Phone03.class;//这个class是全局唯一的,static锁的就是这个对象
public static synchronized void sendSms() throws InterruptedException {
//中间休息4s
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信!");
}


public static synchronized void call(){
System.out.println("打电话!");
}
}

运行结果:

发短信!
打电话!

 

3、答案再次说明

synchronized锁的对象是方法的调用者!静态方法锁的是类;

static方法,类已加载就有了,锁的是class类文件,Phone03这个类只有唯一的一个class类文件;

Class<Phone03> phone03Class = Phone03.class;//这个class是全局唯一的,static锁的就是这个对象;

由于方法执行的时候拿到的是同一把锁,所以谁先拿到锁谁先执行;

 

五、问题6

1、问题

使用两个Phone04的对象进行调用静态方法,是先发短信还是先打电话?

 

2、代码、注释及运行结果

代码及注释:

package com.zibo.lock8;

import java.util.concurrent.TimeUnit;

/**
* 8锁:关于锁的8个问题
* 5、增加两个静态的同步方法,是先发短信还是先打电话?答:先发短信
* 6、使用两个Phone04的对象进行调用静态方法,是先发短信还是先打电话?答:还是先发短信
* 静态方法锁的是类,与对象无关!
*/
public class Test04 {
public static void main(String[] args) throws InterruptedException {
//使用两个Phone04的对象进行调用静态方法
//答案解析:静态方法锁的是类,与对象无关!
Phone04 phone1 = new Phone04();
Phone04 phone2 = new Phone04();
//两个线程,一个发短信,一个打电话
new Thread(() -> {
try {
phone1.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
//中间休息1s
TimeUnit.SECONDS.sleep(1);
new Thread(() -> phone2.call(),"B").start();
}
}

class Phone04{

//synchronized锁的对象是方法的调用者!静态方法锁的是类
//static方法,类已加载就有了,锁的是class类文件,Phone03只有唯一的一个class类文件
//由于方法执行的时候拿到的是同一把锁,所以谁先拿到锁谁先执行
//Class<Phone03> phone03Class = Phone03.class;//这个class是全局唯一的,static锁的就是这个对象
public static synchronized void sendSms() throws InterruptedException {
//中间休息4s
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信!");
}


public static synchronized void call(){
System.out.println("打电话!");
}
}

运行结果:

发短信!
打电话!

 

3、答案再次说明

静态方法锁的是类,与对象无关!

 

6、问题7和8

1、问题

一个静态同步方法、一个普通同步方法,一个对象调用,是先发短信还是先打电话?

一个静态同步方法、一个普通同步方法,两个对象调用,是先发短信还是先打电话?

 

2、代码、注释及运行结果

代码及注释:

package com.zibo.lock8;

import java.util.concurrent.TimeUnit;

/**
* 8锁:关于锁的8个问题
* 7、一个静态同步方法、一个普通同步方法,一个对象调用,是先发短信还是先打电话?答:先打电话!
* 为什么先打电话呢?因为静态方法锁的是Phone05类,普通方法锁的是phone对象,两把锁,互不影响,发短信睡眠4s,打电话肯定先执行完;
* 8、一个静态同步方法、一个普通同步方法,两个对象调用,是先发短信还是先打电话?答:先打电话!
* (非常简单易懂,代码里面就不体现了)
* 为什么先打电话呢?道理是一样的!两把锁,互不影响!
*/
public class Test05 {
public static void main(String[] args) throws InterruptedException {
//使用两个Phone04的对象进行调用静态方法
//答案解析:静态方法锁的是类,与对象无关!
Phone05 phone = new Phone05();
//两个线程,一个发短信,一个打电话
new Thread(() -> {
try {
phone.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
//中间休息1s
TimeUnit.SECONDS.sleep(1);
new Thread(phone::call,"B").start();
}
}

class Phone05{

//静态同步方法
public static synchronized void sendSms() throws InterruptedException {
//中间休息4s
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信!");
}

//普通同步方法
public synchronized void call(){
System.out.println("打电话!");
}
}

 

运行结果:

打电话!
发短信!

 

3、答案再次说明

因为静态方法锁的是Phone05类,普通方法锁的是phone对象,两把锁,互不影响,发短信睡眠4s,打电话肯定先执行完;

 

 

 

 

 

 

 

 

举报

相关推荐

0 条评论