synchronized 原理及JDK1.6后的优化_(1)

      JVM中得同步是基于进入与退出监视器对象(管程对象monitor),来实现的,每个对象实例都会有一个monitor对象,monitor对象会和Java对象一同创建并销毁。monitor对象是由C++实现的。

      当多个线程同时访问一段同步代码时,这些线程会被放到一个EntryList中,处于阻塞状态的线程都会被放到列表当中,接下来,当线程获取到对象monitor时,monitor是依赖于操作系统的mutex Lock来实现互斥,线程获取mutex成功,则会持有该mutex,这时其他线程就无法再获取到该mutex.

       如果线程调用了wait方法,那么线程就会被释放掉所持有的mutex,并且该线程会进入到waitSet集合(等待集合中),等待下一次被其他线程调用notify/notifyAll唤醒。如果当前线程顺利执行完毕方法,那么他也会释放掉所持有的mutex。

      对于synchronized关键字修饰的方法来说,并没有出现monitor与monitorexit指令,而是出现了一个Acc_synchronized标志。

     JVM使用了ACC_synchronized访问标志来区分一个方法是否为同步方法;当方法被调用时,调用指令会检查该方法是否持有Acc_synchronized标志,如果有,那么执行线程将会先持有方法所在对象的monitor对象,然后再去执行放方法体;在该方法执行期间,其他任何线程均无法再获取到这个Monitor对象,当线程执行完毕后,他会释放掉这个Monitor对象。

      实例:

      publicd synchronized void method(){}

        同步锁在这种实现方式当中,因为monitor是依赖于底层的操作系统实现的,这样就存在与用户态和内核态之间的切换,所以会增加性能的开销。

       通过对象互斥锁的概念来保证共享数据操作的完整性,每个对象都对应一个可称为(互斥锁)标记,这个标记用于保证在任何时刻,只能一个线程访问该对象。

      实现同步的同时引入新问题?

      那些处于EntryList与waitSet中的线程均处于阻塞状态,阻塞操作是由操作系统来完成的,在linux下是通过pthread_lock函数来实现的。线程阻塞便会进入到内核调度状态,这会导致系统在用户态和内核态来回切换,严重影响锁的性能。

      解决上述问题的办法便是自选(spin),其原理是:当发生Monitor的争用时,若owner能够在很短的时间内释放掉锁,则那些正在争用的线程就可以稍微等待一下(即所谓的自旋),在owner线程释放之后,争用线程可能会立刻获取到锁,从而避免了系统的阻塞。不过,当owner运行的时间超过了临界值之后,争用线程自选一段时间后依然无法获取到锁,这时争用线程则会停止自选进入到阻塞状态。所以,总体的思想是:先自选--->不成功,则再进入阻塞状态,尽量降低阻塞的可能性,对那些执行时间很短的代码块来说极大的性能提升。显然自旋在多处理器(多核)上才有意义。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值