首页 技术 正文
技术 2022年11月14日
0 收藏 574 点赞 3,489 浏览 1670 个字

认识synchronized

对于写多线程程序的人来说,经常碰到的就是并发问题,对于容易出现并发问题的地方加上synchronized修饰符基本上就搞定 了,如果说不考虑性能问题的话,这一招绝对能应对百分之九十以上的情况,若对于性能方面有要求的话就需要额外的知识比如读写锁等等。本文目的先了解透彻synchronized的基本原理。

Synchronized的基本使用

Synchronized的作用主要有三个: 
(1)确保线程互斥的访问同步代码 
(2)保证共享变量的修改能够及时可见 
(3)有效解决重排序问题。 
从语法上讲,Synchronized总共有三种用法: 
      (1)修饰普通方法 
    (2)修饰静态方法 
    (3)修饰代码块 
  

package com.paddx.test.concurrent;
public class SynchronizedDemo {
   public void method() {
       synchronized (this) {
           System.out.println(“Method 1 start”);
       }
   }
}

对于上述方法我们很容易就知道是线程安全的,具体是怎么做的到的线程安全呢,对class通过javap编译结果如下:

monitorenter

每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:

1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。

2、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.

3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。

monitorexit

执行monitorexit的线程必须是objectref所对应的monitor的所有者。

指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。 
  通过这两段描述,我们应该能很清楚的看出Synchronized的实现原理,Synchronized的语义底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。

原理总结

每个对象都有一个内部的锁或者叫做是监视器,称之为monitor,当一个方法加上synchronized关键字的时候,如果一个线程想执行这个方法那么首先需要获取这个对象的monirot权限,对应到指令上面也就是需要获取monitorenter 指令,如果一个对象获取到这个指令之后,那么monitor的进入数为1,当其他线程再次获取的时候发现这个对象的monitor对象被别的线程所占用,那么进入阻塞状态,知道占用这个对象的线程执行monitorexit,设置进入数为0为止。

如果synchronized加在普通方法上,那么有效的范围是多个线程执行同一个对象的方法。通过上面的解释应该比较容易理解了,因为不同的对象获取的是不同的monitor监视器,自然也就不存在占用–等待的过程了。如果是加载static方法上那么需要获取的就是这个对象所在class的Class对象,所以此时不管是几个对象,对应的都是同一个class对象,也就是说多个线程又存在对同一个monitor的占用—等待的过程了。所以说加载static上是对于整个类文件有效。

转载自– https://www.cnblogs.com/jurendage/p/8691975.html

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,105
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,582
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,429
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,200
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,836
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,919