JUC-02-8锁现象

现象一

多个线程使用一把锁,也就是调用同一个对象,谁先调用谁先执行

被 synchronized 修饰的方法、锁的对象是方法的调用者


public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 两个线程使用同一个对象(同一把锁)
        Phone phone = new Phone();

        new Thread(()->{phone.sendMessage();}).start();

        TimeUnit.SECONDS.sleep(3); // 中途睡眠

        new Thread(()->{phone.call();}).start();
    }
}

class Phone {
	// 被 synchronized 修饰的方法、锁的对象是方法的调用者、
    public synchronized void sendMessage(){
        System.out.println("发短信");
    }

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

现象二

多个线程使用同一把锁,某个锁方法里有阻塞,依旧是谁先调用谁先执行

public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 两个线程使用同一个对象(同一把锁)
        Phone phone = new Phone();

        new Thread(()->{
            phone.sendMessage();
        }).start();

        TimeUnit.SECONDS.sleep(3); // 中途睡眠

        new Thread(()->{
            phone.call();
        }).start();
    }
}

class Phone {

	// 被 synchronized 修饰的方法、锁的对象是方法的调用者、
    public synchronized void sendMessage(){
    	// 添加阻塞
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

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

现象三

多个线程中既有 有锁方法 也有无锁方法 会 随机执行

public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 两个线程使用同一个对象(同一把锁)
        Phone phone = new Phone();

        new Thread(()->{
            phone.sendMessage();
        }).start();

        TimeUnit.SECONDS.sleep(3); // 中途睡眠

        new Thread(()->{
            phone.call();
        }).start();
    }
}

class Phone {

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

    // 这里是无锁方法
    public void call(){
        System.out.println("打电话");
    }
}

现象四

多个线程调用多个对象,多个线程使用多把锁, 会随机执行
Synchronized 锁的是方法调用者,两个线程调用两个不同的对象,所以互不干扰

package com.it.lock8;

import java.util.concurrent.TimeUnit;

/**
 * @author shkstart
 * @create 2020-06-18 9:21
 */

public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 两个线程分别使用两把锁
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(()->{
            phone1.sendMessage();
        }).start();

        TimeUnit.SECONDS.sleep(3); // 中途睡眠

        new Thread(()->{
            phone2.call();
        }).start();
    }
}

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

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

现象五

Class锁,static和synchronized 修饰的方法
多个线程使用一个对象(一把锁)但是被 static修饰 ,锁的是class文,全局只有一个 会 顺序执行

被 synchronized 和 static 同时修饰的方法,锁的对象是类的 class 对象,是唯一的一把锁。线程之间是顺序执行。
锁Class和锁对象的区别:
1、Class 锁 ,类模版,只有一个;
2、对象锁 , 通过类模板可以new 多个对象

public class Test {

   public static void main(String[] args) throws InterruptedException {

       // 两个线程使用同一把锁
       Phone phone = new Phone();

       new Thread(()->{
           phone.sendMessage();
       }).start();

       TimeUnit.SECONDS.sleep(3); // 中途睡眠

       new Thread(()->{
           phone.call();
       }).start();
   }
}

class Phone {

   // synchronized 锁的对象是方法的调用者!
   // static 和 synchronized 同时修饰锁的是class
   public static synchronized void sendMessage(){
       try {
           TimeUnit.SECONDS.sleep(3);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("发短信");
   }


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

现象六

Class锁,static和synchronized 修饰的方法
多个线程使用多个对象(多把锁)但是被 static修饰 ,锁的是class文,全局只有一个 会 顺序执行

public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 两个线程分别使用两把锁
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(()->{
            phone1.sendMessage();
        }).start();

        TimeUnit.SECONDS.sleep(3); // 中途睡眠

        new Thread(()->{
            phone2.call();
        }).start();
    }
}
// class 是唯一的class对象
class Phone {

    // synchronized 锁的对象是方法的调用者!
    // static 和 synchronized 同时修饰锁的是class
    public static synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }


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

现象七

一个静态同步方法 一个普通同步方法
多个线程去操作同一个对象 会先执行普通同步方法

public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 两个线程分别使用两把锁
        Phone phone = new Phone();

        new Thread(()->{
            phone.sendMessage();
        }).start();

//        TimeUnit.SECONDS.sleep(3); // 中途睡眠

        new Thread(()->{
            phone.call();
        }).start();
    }
}
// class 是唯一的class对象
class Phone {

    // synchronized 锁的对象是方法的调用者!
    // static 和 synchronized 同时修饰锁的是class
    public static synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }


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

现象八

两个静态同步方法,两个对象
顺序执行

public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 两个线程分别使用两把锁
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(()->{
            phone1.sendMessage();
        }).start();

//        TimeUnit.SECONDS.sleep(3); // 中途睡眠

        new Thread(()->{
            phone2.call();
        }).start();
    }
}
// class 是唯一的class对象
class Phone {

    // synchronized 锁的对象是方法的调用者!
    // static 和 synchronized 同时修饰锁的是class
    public static synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }


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

总结

  1. 被 synchronized 修饰的方法,锁的对象是方法的调用者(实例对象)

  2. 被 static synchronized 修饰的方法,锁的对象就是 Class模板对象,这个则全局唯一

synchronized修饰的 多个线程调用单个对象(一把锁) 顺序执行

synchronized 修饰的 多个线程调用多个对象(多把锁) 随机执行

因为synchronized修饰 锁的是方法调用者(对象),
所以单个对象的时候谁先调用谁就先拿到锁先执行
多个对象的时候根据CPU调度,随机执行



static synchronized 修饰的 多个线程调用单个对象 顺序执行

static synchronized 修饰的 多个线程调用多个对象  顺序执行

因为 static synchronized 修饰 锁的是class 全局唯一
所以单个单个对象或多个对象调用的时候都是顺序执行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值