美文网首页
Sychronized关键字从使用到深入

Sychronized关键字从使用到深入

作者: codingBen | 来源:发表于2018-02-23 00:37 被阅读0次

    Synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 

    1. 修饰一个代码块:被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 

    2. 修饰一个方法:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 

    3. 修饰一个静态的方法:其作用的范围是整个静态方法,作用的对象是这个类的所有对象; 

    4. 修饰一个类:其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

    Synchronized锁重入功能:也就是在使用synchronized时,当一个线程得到了一个对象锁之后,再次请求此对象是可以再次得到该对象的锁的

    Synchronized和Before/After模式

    不管是Synchronized方法还是synchronized代码块都像是一个由"{"和"}"包起来的一个代码块.如下所示

    //synchronzied方法

    synchronized void method{

        ...

    }

    //synchronized代码块

    synchronized(obj){

        ...

    }

    但是一般的锁处理如下所示:

    //锁处理的方法

    void method(){

        lock();

        ...

        unlock();

    }

    看起来这样的两个方法都是一样的,但是如果在lock()和unlock()之间存在return或者异常处理时就会出现锁无法释放的问题.

    但是对于synchronized方法或者synchronized代码来说无论是中间执行了return或者还是异常处理都一定能释放锁.

    如何解决这个问题?

    //锁处理的方法

    void method(){

        lock();

        try{

            ...

        }

        finaly{

            unlock();

        }

    }

    在如上所示的代码中,不管是中间执行了return,抛出异常,还是其他任何操作,finally部分的代码都会被运行.

    这种finally用法是Before/After模式的实现方法之一.

    Synchronized与原子操作

    synchronized方法只允许一个线程同步执行,如果某个线程正在执行synchronized方法,其他线程就无法进入该方法.所以syncrhonized修饰的操作被成为原子操作.

    Java中的原子操作

    (1) 除long和double之外的基本类型的赋值操作

    (2) 所有引用reference的赋值操作

    (3) java.concurrent.Atomic.* 包中所有类的一切操作。

    比如对long和double这种在32位操作系统下会出现非原子操作的数据类型,我们应该用Synchronized或者volatile来修饰.

    Synchronized原理-Monitor

    看到这里很多同学可能会觉得奇怪,为什么在Java中不管什么对象都可以被作为锁?而且作为所有的类的顶级对象Object中的Object方法都有nofity/notifyAll/wait等方法.这是因为对于Java中任意一个对象都对应有一个Monitor对象,它拥有关于锁的一切信息.

    我们都知道Java对象都存在堆中,对于每一个对象,它都由三个部分组成:1.对象头2.实例数据3.对齐填充

    在JVM中,对象在内存中的布局分为三块区域:1.对象头,2.实例数据3,对齐填充

    在Java对象头中主要由Mark WordClass Metadata Address组成.

    Mark Word: 存储对象的hashCode、锁信息或分代年龄或GC标志等信息

    Class Metadata Address: 类型指针指向对象的类元数据,JVM通过这个指针确定该对象是哪个类的实例。

    Moniter对象便是对我们每个Java对象的头里的Mark Word存在的对象.通过对Java对象的Mark Word中属性的监视,来进行锁管理.,

    在Java虚拟机(HotSpot)中,monitor是由ObjectMonitor实现的,ObjectMonitor中有两个队列,_WaitSet 和 _EntryList用来保存ObjectWaiter对象列表( 每个等待锁的线程都会被封装成ObjectWaiter对象),_owner指向持有ObjectMonitor对象的线程,当多个线程同时访问一段同步代码时,首先会进入 _EntryList 集合,当线程获取到对象的monitor 后进入 _Owner 区域并把monitor中的owner变量设置为当前线程同时monitor中的计数器count加1,若线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时该线程进入 WaitSe t集合中等待被唤醒。若当前线程执行完毕也将释放monitor(锁)并复位变量的值,以便其他线程进入获取monitor(锁)。

    相关文章

      网友评论

          本文标题:Sychronized关键字从使用到深入

          本文链接:https://www.haomeiwen.com/subject/qyxbtftx.html