java多线程之线程八锁案例

1.八锁现象
如何判断锁的是谁?永远的知道什么锁,锁到底锁的是谁?
深刻理解我们的锁!

1.标准情况下,两个线程先打印.是先发短信还是打电话?

public class Teat01 {
    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{public synchronized void sendSms(){
​        System.out.println("sendSms");}public synchronized void call(){
​        System.out.println("call");}
}

在这里插入图片描述结果:第一个是发短信第二个是打电话.是固定不变的.

2.sendSms延迟四秒,同样执行程序是先执行发短信还是打电话

public class Teat01 {
    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{public synchronized void sendSms(){try {
​            TimeUnit.SECONDS.sleep(4);//再给A线程延迟4秒} catch (InterruptedException e) {
​            e.printStackTrace();}
​        System.out.println("sendSms");}public synchronized void call(){
​        System.out.println("call");}

结果如下:
在这里插入图片描述
还是等了A线程执行后,再执行call

3.在Phone2中添加一个方法,输出为hello,不是同步锁,B线程,调用hello方法,请问是先执行发短信还是输出hello

public class Test02 {
    public static void main(String[] args) {
        Phone2 phone = new Phone2();
        new Thread(()->{
            phone.sendSms();
        },"A").start();
        try {
            //捕获
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }new Thread(()->{
​            phone.hello();},"B").start();}

}
class  Phone2{
    //synchronized 锁的对象,是方法的调用者!上面代码new了一个对象,开了两个线程.所以用的是同一把锁(phone的锁)
    //谁先拿到谁就执行
    public synchronized void sendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendSms");
    }
    public synchronized void call(){
        System.out.println("call");
    }
    //这里没有锁,没有同步方法,不受锁的影响.
    public void hello(){
        System.out.println("Hello");
    }

在这里插入图片描述
小结论:这里没有锁,没有同步方法,不受锁的影响.所以延迟执行的,自然没有普通方法执行快

4.同上代码:增加一个对象,两个对象,两个同步方法,同时执行

//两个对象

Phone2 phone = new Phone2();
Phone2 phone2 = new Phone2();

 new Thread(()->{
            phone.sendSms();
        },"A").start();
        
         new Thread(()->{
            phone2.call();
        },"B").start();
        

在这里插入图片描述结果为:打电话先执行,原因是两个对象两把锁互不影响,由于,发短信延迟了4秒,所以毋庸置疑,call先于sendSms

5.增加两个静态的同步方法 +Static

同上代码:在synchronized前面加上static,请问那个先执行

public static synchronized void call(){
    System.out.println("call");
}

public static synchronized void sendSms(){}

结果:在这里插入图片描述
原因:static为静态方法,和类加载时一起执行的.和synchronized现在锁的不是调用者,而是模板

如:Class phone3Class = Phone3.class;锁这个Class模板,Phone3唯一的一个Class对象

6.两个对象!增加两个静态的同步方法,是先执行发短信还是打电话?

hone3 phone2 = new Phone3();
  new Thread(()->{
            phone2.call();
        },"B").start();

在这里插入图片描述
原因:两个对象Class模板只有一个,与两个对象无关了,Static锁的是Class,所有说还是发短信在前面

7.一个静态同步方法,和一个普通同步方法

代码变化:

Phone4 phone = new Phone4();

public static synchronized void sendSms(){//锁的是Class类模板
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendSms");
        
        public synchronized void hello(){
        System.out.println("Hello");
    }

在这里插入图片描述
原因:首先静态同步方法锁的是Class模板,但是该方法有延时,而普通的同步方法锁的是phone的调用对象,两个方法不是用的一把锁所以先走Hello方法

8.一个静态同步方法,和一个普通同步方法,两个对象

代码:

package com.lock8;

import java.util.concurrent.TimeUnit;

/**

 * 8锁就是关于锁的八个问题
 * 1.标准情况下,两个线程先打印.是先发短信还是打电话?结果:第一个是发短信第二个是打电话.是固定不变的.
 * 2.sendSms延迟四秒,同样执行程序是先执行发短信还是打电话
 * 3.再Phone2中添加一个方法,输出为hello,不是同步锁,B线程,调用hello方法,请问是先执行发短信还是输出hello
 * 4.两个对象,两个同步方法,同时执行
 * 5.增加两个静态的同步方法 +Static:
 * 6.两个对象!增加两个静态的同步方法,是先执行发短信还是打电话?
 * 7.一个静态同步方法,和一个普通同步方法,一个对象
 * 8.一个静态同步方法,和一个普通同步方法,两个对象

 */
public class Test04 {
    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();}

}
//Phone3唯一的一个Class对象
class  Phone4{
    //static 静态方法
    //类一加载就有了,Class 模板
    //synchronized 锁的对象,是方法的调用者!public static synchronized void sendSms(){//锁的是Class类模板try {
​            TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {
​            e.printStackTrace();}
​        System.out.println("sendSms");
​        Class<Phone3> phone3Class = Phone3.class;}public synchronized void call(){
​        System.out.println("call");}public synchronized void hello(){
​        System.out.println("Hello");}
}

在这里插入图片描述
原因:两个锁的对象不一样,而发短信有延迟,所以打电话先执行

小结:

一个是new 一个是static
new this 具体的一个手机
static Class 唯一的一个模板

原创文章 32 获赞 52 访问量 644

猜你喜欢

转载自blog.csdn.net/qq_42400763/article/details/105800849