前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >8锁问题

8锁问题

作者头像
西柚dzh
发布2022-06-09 17:07:09
1940
发布2022-06-09 17:07:09
举报
文章被收录于专栏:dcmickey小站dcmickey小站

8锁问题

场景一

标准情况访问:两个同步方法,一个对象调用

代码语言:javascript
复制
import java.util.concurrent.TimeUnit;

/**
 * 标准情况下 是先sendEmail() 还是先callPhone()?
 * 答案:sendEmail
 * 解释:被 synchronized 修饰的方式,锁的对象是方法的调用者
 * 所以说这里两个方法调用的对象是同一个,先调用的先执行!
 */
public class LockDemo1 {
    public static void main(String[] args) throws InterruptedException {
        Phone1 phone1 = new Phone1();
        new Thread(()->{
            phone1.sendEmail();
        },"A").start();
        TimeUnit.SECONDS.sleep(3);
        new Thread(()->{
            phone1.callPhone();
        },"B").start();
    }
}
class Phone1{
    public synchronized void sendEmail(){
        System.out.println("senEmail");
    }
    public synchronized  void callPhone(){
        System.out.println("callPhone");
    }
}

原因:synchronized 锁的是方法的调用者,也就是对象锁。两个方法持有的是同一把锁,因此谁先拿到锁谁先执行。

场景二

两个同步方法,一个对象调用 在其中一种方法中添加sleep方法访问

代码语言:javascript
复制
import java.util.concurrent.TimeUnit;

/**
 * sendEmail()休眠三秒后  是先执行sendEmail() 还是 callPhone()
 * 答案: sendEmail
 * 解释:被 synchronized 修饰的方式,锁的对象是方法的调用者
 * 所以说这里两个方法调用的对象是同一个,先调用的先执行!
 */
public class LockDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Phone2 phone2 = new Phone2();
        new Thread(()->{
            try {
                phone2.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();
        TimeUnit.SECONDS.sleep(2); // 休眠2秒
        new Thread(()->{
            phone2.callPhone();
        },"B").start();
    }
}
class Phone2{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }
    public synchronized void callPhone(){
        System.out.println("callPhone");
    }
}

原因:synchronized 锁的是方法的调用者,也就是对象锁。两个方法持有的是同一把锁,因此谁先拿到锁谁先执行

场景三

一个同步方法,其中一个改为普通方法,还是一个对象调用

代码语言:javascript
复制
import java.util.concurrent.TimeUnit;

/**
 * 被synchronized 修饰的方式和普通方法 先执行sendEmail() 还是 callPhone()
 * 答案: callPhone
 * 解释:新增加的这个方法没有 synchronized 修饰,不是同步方法,不受锁的影响!
 */
public class LockDemo3 {
    public static void main(String[] args) throws InterruptedException {
        Phone3 phone3 = new Phone3();
        new Thread(()->{
            try {
                phone3.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(2);
        new Thread(()->{
            phone3.callPhone();
        },"B").start();
    }
}
class Phone3{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }

    // 没有synchronized 没有static 就是普通方式
    public void callPhone(){
        System.out.println("callPhone");
    }
}

原因:普通方法没有锁,不需要竞争锁。

场景四

两个同步方法,两个对象调用

代码语言:javascript
复制
import java.util.concurrent.TimeUnit;

/**
 * 被synchronized 修饰的不同方法 先执行sendEmail() 还是callPhone()?
 * 答案:callPhone
 * 解释:被synchronized 修饰的不同方法 锁的对象是调用者
 * 这里锁的是两个不同的调用者,所有互不影响
 */
public class LockDemo4 {
    public static void main(String[] args) throws InterruptedException {
        Phone4 phoneA = new Phone4();
        Phone4 phoneB = new Phone4();

        new Thread(()->{
            try {
                phoneA.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phoneB.callPhone();
        },"B").start();
    }
}
class Phone4{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }
    public synchronized void callPhone(){
        System.out.println("callPhone");
    }
}

原因:synchronized 锁的是方法的调用者,也就是对象锁。两个对象分别调用两个方法持有的是两把锁

场景五

两个静态同步方法,一个对象调用

代码语言:javascript
复制
import java.util.concurrent.TimeUnit;

/**
 * 两个静态同步方法 都被synchronized 修饰 是先sendEmail() 还是callPhone()?
 * 答案:sendEmial
 * 解释:只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!
 *      所以说这里是同一个锁,并不是因为synchronized  这里程序会从上往下依次执行
 */
public class LockDemo5 {
    public static void main(String[] args) throws InterruptedException {
        Phone5 phone5 = new Phone5();
        new Thread(()->{
            try {
                phone5.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phone5.callPhone();
        },"B").start();
    }
}
class Phone5{
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

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

原因:static方法类一加载就执行,synchronized 锁的是Class对象即类所,所以两个方法持有一把锁,谁先得到谁先执行。

场景六

两个静态同步方法,两个对象调用

代码语言:javascript
复制
import java.util.concurrent.TimeUnit;

/**
 * 同被static+synchronized 修饰的两个方法,是先sendEmail()还是callPhone()?
 *  答案:sendEmail
 *  解释:只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一
 *  所以说这里是同一个锁,并不是因为synchronized
 */
public class LockDemo7 {
    public static void main(String[] args) throws InterruptedException {
        Phone7 phoneA = new Phone7();
        Phone7 phoneB = new Phone7();

        new Thread(()->{
            try {
                phoneA.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phoneB.callPhone();
        },"B").start();
    }
}
class Phone7{
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

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

场景七

一个静态同步方法,一个改为普通同步方法,一个对象调用

代码语言:javascript
复制
import java.util.concurrent.TimeUnit;

/**
 * 被synchronized 修饰的普通方法和静态方法  是先sendEmail() 还是 callPhone()?
 * 答案:callPhone
 * 解释:只要被static修饰锁的是class模板, 而synchronized 锁的是调用的对象
 * 这里是两个锁互不影响,按时间先后执行
 */
public class LockDemo6 {
    public static void main(String[] args) throws InterruptedException {
        Phone6 phone6 = new Phone6();
        new Thread(()->{
            try {
                phone6.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phone6.callPhone();
        },"B").start();
    }
}
class Phone6{
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

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

只要被static修饰锁的是class模板, 而synchronized 锁的是调用的对象,这里是两个锁互不影响,按时间先后执行

场景八

一个静态同步方法,一个普通同步方法,两个对象调用

代码语言:javascript
复制
import java.util.concurrent.TimeUnit;

/**
 * 一个被static+synchronized 修饰的方法和普通的synchronized方法,先执行sendEmail()还是callPhone()?
 * 答案:callPhone()
 * 解释: 只要被static 修饰的锁的就是整个class模板
 * 这里一个锁的是class模板 一个锁的是调用者 
 * 所以锁的是两个对象 互不影响
 */
public class LockDemo8 {
    public static void main(String[] args) throws InterruptedException {
        Phone8 phoneA = new Phone8();
        Phone8 phoneB = new Phone8();

        new Thread(()->{
            try {
                phoneA.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phoneB.callPhone();
        },"B").start();
    }
}
class Phone8{
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

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

总结

  • static synchronized 锁的是class类模板,全局唯一,谁先抢到谁执行
  • synchronized 锁的是new 出来的那个调用者,不同调用者互相独立各自有锁

版权属于:dingzhenhua

本文链接:https://cloud.tencent.com/developer/article/2019336

转载时须注明出处及本声明

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 8锁问题
    • 场景一
      • 场景二
        • 场景三
          • 场景四
            • 场景五
              • 场景六
                • 场景七
                  • 场景八
                    • 总结
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档