8锁问题

suaxi
2021-01-06 / 0 评论 / 90 阅读 / 正在检测是否收录...

8锁问题

什么是锁?锁的对象是谁?

package com.sw.lock8;

import java.util.concurrent.TimeUnit;

/**
 * @Author suaxi
 * @Date 2021/1/4 15:44
 * 1、执行顺序:发短信  打电话
 * 2、增加睡眠时间后,执行顺序:发短信  打电话
 */
public class Test1 {
    public static void main(String[] args) {
        Phone1 phone1 = new Phone1();

        new Thread(() ->{
            phone1.sms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() ->{
            phone1.call();
        },"B").start();
    }
}


class Phone1{

    //synchronized锁的对象是方法的调用者
    //两个方法用的是同一个锁,谁先拿到锁,谁先调用
    public synchronized void sms(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public synchronized void call(){
        System.out.println("打电话");
    }
}
package com.sw.lock8;

import java.util.concurrent.TimeUnit;

/**
 * @Author suaxi
 * @Date 2021/1/4 15:51
 * 3、增加一个hello的普通方法后,执行顺序为 hello  发短信
 * 4、两个对象、两个同步方式,执行顺序为 打电话  发短信
 */
public class Test2 {
    public static void main(String[] args) {
        //两个对象、两个调用者、两把锁
        Phone2 phone1 = new Phone2();
        Phone2 phone2 = new Phone2();

        new Thread(() ->{
            phone1.sms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() ->{
            phone2.call();
        },"B").start();
    }
}


class Phone2{

    //synchronized锁的对象是方法的调用者
    public synchronized void sms(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

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

    //普通方法不受锁的限制
    public void hello(){
        System.out.println("hello");
    }
}
package com.sw.lock8;

import java.util.concurrent.TimeUnit;

/**
 * @Author suaxi
 * @Date 2021/1/4 15:58
 * 5、增加static后,执行顺序为 发短信  打电话
 * 6、两个Phone对象,执行顺序依然为为 发短信  打电话
 */
public class Test3 {
    public static void main(String[] args) {
        //两个对象的Class类模板只有一个,与问题5一样锁的也是Class
        Phone3 phone = new Phone3();
        Phone3 phone1 = new Phone3();

        new Thread(() ->{
            phone.sms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() ->{
            phone1.call();
        },"B").start();
    }
}


class Phone3{

    //synchronized锁的对象是方法的调用者
    //static静态方法,类一加载就有了,此处锁的是Class对象
    public static synchronized void sms(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public static synchronized void call(){
        System.out.println("打电话");
    }
}
package com.sw.lock8;

import java.util.concurrent.TimeUnit;

/**
 * @Author suaxi
 * @Date 2021/1/4 16:05
 * 7、1个静态同步方法,1个普通同步方法,一个对象,执行顺序 打电话  发短信
 * 8、1个静态同步方法,1个普通同步方法,两个对象,执行顺序 打电话  发短信
 */
public class Test4 {
    public static void main(String[] args) {
        //两个对象的Class类模板只有一个,与问题5一样锁的也是Class
        Phone4 phone1 = new Phone4();
        Phone4 phone2 = new Phone4();

        new Thread(() ->{
            phone1.sms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() ->{
            phone2.call();
        },"B").start();
    }
}


class Phone4{

    //静态同步方法  锁的是Class类模板
    public static synchronized void sms(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    //普通同步方法  锁的是调用者,不需要再等待发短信的sleep睡眠时间,两个方法用的不是同一个锁
    public synchronized void call(){
        System.out.println("打电话");
    }
}
小结

一个对象,拿的是同一把锁

两个对象拿的是不同的锁

加了static静态方法之后,不论有几个对象,锁的只有一个Class模板

普通方法不受锁的限制

0

评论 (0)

取消