Java Thread Synchroize两种方式的优劣

Context:

关于Thread老是看了忘,看了忘记。还是写下来吧。翻译的是orcale官网的锁解释文档地址


锁:

   同步机制是围绕内部实体即intrinsic lock(intrinsic固有的、本质的)、monitor lock(监控锁)。Intrinsic lock在同步上扮演两个角色:1.强制的排他性读取对象的状态(也就是线程访问对象的属性、方法等是互斥的)、2保持happens-before relationship来确保变量、方法的可见性。

  每个对象都有与其关联的intrinsic lock。按照惯例,一个线程需要 排他的、一致性(consistent)读取对象的属性,必须获取该对象的锁。并在处理完后释放intrinsic lock。在线程获取和释放锁之间,线程被称为拥有intrinsic lock。只要一个线程持有intrinsic lock,其他的线程尝试获取这个锁时就会被阻塞。


两种Synchronized:

Synchronized方法:

用法: public synchronized void sayHello(){}

a)非静态方法:intrinsic lock是该调用方法的对象,如b.sayHello  线程持有的intrinsic lock就是对象b的intrinsic lock

b) 静态方法:例如 public static synchronized void getInstance()。调用是Test.getInstance();这里没有对象,线程持有的intrinsic lock是Test对象对应的Class类的对象,也就是假设Test类的对象testObject.getClass()所获得的对象。而该对象是在类的加载(Loading)阶段 在Java堆中生成一个代表改类的java.lang.Class对象,作为方法区的访问入口。(详见我以前的博客点击打开链接   )所以他是类级别的锁。

Synchronized声明:

用法:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}
a)不是用该方法的对象来做为intrinsic lock,而是你指定任意一个对象

好处

1:不对整个方法进行同步,而是对一部分进行同步,效率要高些,也更安全(从同步的方法中调用别的对象的方法,可能造成Liveness问(如:死锁)。如例子,就没有吧nameList.add(name);加到里面。

:

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }

    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
    }
}
2.c1的改变和c2的改变没什么逻辑上的关联,可以两个线程交叉改变。所以就没有必要用Synchronized Method,否则锁是该方法对象,两个inc1、inc2无法被两个线程同时访问。


重新进入Synchronized:

虽然a线程无法进入b线程锁住的方法,但是b线程可以再次进入b线程持有锁的方法,并对锁的进入进行累加。这样就可以递归调用了嘛。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值