哪个对象才是锁?

2 篇文章 0 订阅
2 篇文章 0 订阅

转载自:http://ifeve.com/who-is-lock/

我们都知道当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。这些基础也许大家都知道,但是很多人还是搞不清哪个对象才是锁?如果你能正确回答以下问题,那么才算你彻底搞明白了哪个对象才是锁?

静态同步方法问题

如下代码是两个静态同步方法

Class A{
    public static synchronized void write(boolean b){
        isTrue = b;
    }
 
    public static synchronized boolean read(){
        return isTrue;
    }
}

那么我们来问几个问题

  1. 线程1访问A.write(true)方法时,线程2能访问A.read()方法吗?
  2. 线程1访问new A().write(false)方法时,线程2能访问new A().read()方法吗?
  3. 线程1访问A.write(false)方法时,线程2能访问new A().read()方法吗?

实例同步方法问题

如下代码是两个实例同步方法

public synchronized void write(boolean b){
    isTrue = b;
}

public synchronized boolean read(){
    return isTrue;
}

同样问两个问题:

  1. A a=new A(); 线程1访问a.write(false)方法,线程2能访问a.read()方法吗?
  2. A a=new A(); A b=new A();线程1访问a.write(false)方法,线程2能访问b.read()方法吗?

回答问题之前,先想一下当前方法使用的锁是哪一个?当前线程是否有拿到这把锁?拿到锁了就能访问当前方法了。

答案

我们先回顾基础知识,Java中的每一个对象都可以作为锁,而不同的场景锁是不一样的。

  1. 对于实例同步方法,锁是当前实例对象。
  2. 对于静态同步方法,锁是当前对象的Class对象。
  3. 对于实例同步方法块,锁是Synchonized括号里配置的对象。
  4. 对于静态同步方法块,锁是Synchronized括号配置的类的Class对象。(一般是当前类的Class对象)

线程1访问A.write()方法时,线程2能访问A.read()方法吗?不能,因为静态方法的锁都是A.Class对象,线程1拿到锁之后,线程2就拿不到锁了。

线程1访问new A().write()方法时,线程2能访问new A().read()方法吗?不能,原因同上。

线程1访问A.write()方法时,线程2能访问new A().read()方法吗?不能,原因同上

A a=new A(); 线程1访问a.write()方法,线程2能访问a.read()方法吗?不能,因为这两个方法的锁都是对象a,线程1拿到了锁,线程2就不能访问了。

A a=new A(); A b=new A();线程1访问a.write()方法,线程2能访问b.read()方法吗?可以,因为线程1拿到的是锁是 a,而线程2访问b.read()需要的是锁是b。

现在你应该明白了这句话,对于实例同步方法,锁是当前实例对象。对于静态同步方法,锁是当前对象的Class对象


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值