• 前言: 

  synchronize会使用,但是对于深层次的知识,不是很清楚,故整理一篇博客。

简介:

  能够保证在同一时刻,最多只有一个线程执行该端代码,以达到保证并发安全效果。

两种用法:

  • 对象锁
包括方法锁(默认锁对象为this当前实例对象) 锁某个方法

同步代码块锁(自己制定锁对象) 锁某块代码
  • 类锁
指synchronized修饰静态的方法或指定锁为Class对象

概念: Java类可能有很多个对象,但只有一个Class对象。

本质: 所谓的类锁,不过是Class对象的锁而已。

对线程访问同步方法的7种情况:

  1. 两个线程同时访问一个对象的同步方法

  2. 两个线程访问的是两个对象的同步方法

  3. 两个线程访问的是synchronized的静态方法: 静态方法带synchronized

  4. 同时访问同步方法和非同步方法,非同步方法不受影响

  5. 访问同一个对象的不同的普通同步方法

  6. 同时访问静态synchronized和非静态synchronized方法

  7. 方法抛异常后,会释放锁

小结核心:

  1. 一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待(1,5情况)

  2. 每个实例都对应有自己的一把锁,不同实例之间互不影响。例如: 锁对象是.class以及synchronized修饰的是static方法的时候,所有对象共用同一把锁(对应第2,3,4,6情况)

  3. 不论是方法正常执行完毕或者方法抛出异常,都会释放锁(7情况)

 

synchronize性质:

  • 可重入       方法可以重入,父子类可以重入
  • 不可中断     一旦这个锁已经被被人获得了,如何我还想获得,我只能选择等待或者阻塞,知道别的线程释放这个锁。而Lock类,拥有中断能力。第一点,如果我觉得我等待时间长了。有权中断现在已经获取到锁的线程的执行。第二点,如果我觉得我不想等待了,可以退出。

原理:

  • 加锁原理
  • 可重入原理
  • 可见性原理

调试方法:

可以看到线层的状态:

原理:

加锁和释放锁的原理:

现象: 每一个类的实例对应一把锁,每一个synchronized方法都必须获得调用该方法的实例的锁才可以执行,否则阻塞。

我们指定对象就可以了,锁的释放获取由JVM去自动实现。

获取和释放锁的时机: 内置锁

每一个Java对象都可以用作实现一个同步的锁,这个锁称之为内置锁(监视器锁)。线程在家进入代码块之前,会自动获取这个锁。退出代码块时候会自动释放锁。

获得这个内置锁的唯一途径,就是进入到这个锁保护的代码块或者方法中。

  加锁和释放锁的原理: 深入JVM

每一个对象都有个对象头,可以存储很多信息。

Monditorenter 和 Monditorexit指令

(联想操作系统知识:临界区)

每个对象都与Monitor相关联,而一个Monitor的lock锁只能被一个线程同一时间获得。

一个线程尝试获得与这个对象关联的Monitor所有权到时候,只会发生以下三种:

1. Monitor计数器为0,目前还没有被获得,线程获取后计数器加1.

2. 如果Monitor已经拿到了锁的所有权,又重入了。这样导致计数器累加。

3. 如果Monitor已经被其他线程持有了。我去获取时候,只能阻塞状态了。知道技术器变为0,再去尝试获取锁。

关于Monditorexit:

释放对于Monitor的所有权,释放过程就是将Monitor计数器减1.如果减完是0,当前线程不再拥有对Monitor的所有权了,其他的阻塞线程会再次尝试获取对该把锁的所有权,不是0这是可重入进来的,可以继续持有这把锁。

可重入原理: 加锁次数计数器

JVM负责跟踪对象被加锁的次数。每个对象都含有一把锁,JVM负责跟踪对象被加锁的次数。

线程第一次给对象加锁的时候,技术变为1.每当这个相同的线程在此对象上再次获得锁时,计数会递增。

每当任务离开时候,技术递减,当计数为0到时候,锁被完全释放。

synchronized缺陷:

效率低: 锁的释放情况少,视图获得锁时候不能设置超时,不能中断一个正在试图获得锁的线程。

不够灵活(读写锁更灵活): 加锁和释放的时机单一,每个锁仅有单一的条件(某个对象),可能不够 。

无法知道是否成功获取到锁

反编译: javap    -verbose  xx.class

问题总结:

 1. 使用注意点:

         锁对象不能为空(锁信息保存在头部,对象都没有,怎么玩儿),作用域不宜过大(包裹的代码块),避免死锁。

 2. 如何选择Lock和synchronized关键字

        

思考:

1. 多个线程等待同一个synchronized锁的时候,JVM如何选择下一个获取锁的是哪个线程?

    等待时间最长,随机?

2. Synchronized使得同时只有一个线程可以执行,性能较差,有什么办法可以提升性能?

    优化使用范围

    使用其它类型的锁,读写锁

3. 我想更灵活的控制锁的获取和释放(现在释放锁的时机都规定死了),怎么办?

    自己实现lock接口,可控

4. 什么是锁的升级,降级。什么是JVM里的偏向锁,轻量级锁,重量级锁?

   之前的版本中synchronized性能不是很好,经过后面的迭代。利用偏斜锁,轻量级锁,重量级锁。JVM根据synchronized关键字锁使用的次数和种种指标来对锁进行非常有效的优化。还涉及到对象头里面的一些字段。

    

总结:

 JVM会自动通过使用monitor来加锁和解锁,保证了同时只有一个线程可以执行指定代码,从而保证了线程安全,同时具有可重入和不可中断性质。

 

MonitorEnter表示进入对象的监视器当中

Synchronize深入的更多相关文章

  1. Delphi:与VCL同步(Synchronize()、用消息来同步)

    看本文时,可以同时参考:Delphi中线程类 TThread实现多线程编程(事件.临界区.Synchronize.WaitFor……) 先说一下RTL和VCL RTL(Run-Time library ...

  2. delphi中线程应用之Synchronize

    当一个线程在使用时,如果这个函数使用了Synchronize修钸的话就不允许别一个线程来调用这个函数,它的目的是避免多个子线程同时访问主线程资源.示例:procedure TTaskThread.Sh ...

  3. wait() notify()搭配synchronize的使用

    一直以为自己动多线程,使用过好像就懂了原理一样,其实是按部就班的写自己不知道原理的代码而已. 一些概念: 监视器:将监视器比作一个建筑,建筑里面有个特别的房间,房间中有一些数据,这些数据在同一个时间只 ...

  4. Delphi中线程类TThread实现多线程编程2---事件、临界区、Synchronize、WaitFor……

    接着上文介绍TThread. 现在开始说明 Synchronize和WaitFor 但是在介绍这两个函数之前,需要先介绍另外两个线程同步技术:事件和临界区 事件(Event) 事件(Event)与De ...

  5. Effective Java 66 Synchronize access to shared mutable data

    synchronized - Only a single thread can execute a method or block at one time. Not only does synchro ...

  6. How to: Synchronize Files by Using Managed Code

    The examples in this topic focus on the following Sync Framework types: FileSyncProvider FileSyncOpt ...

  7. Synchronization in Delphi TThread class : Synchronize, Queue

    http://embarcadero.newsgroups.archived.at/public.delphi.rtl/201112/1112035763.html > Hi,>> ...

  8. synchronize的心得

    记录一下synchronize(this).synchronize(A.class).private B  b= new B(); synchronize(b) .synchronize static ...

  9. VCL线程的同步方法 Synchronize(用消息来同步)

    看本文时,可以同时参考:Delphi中线程类 TThread实现多线程编程(事件.临界区.Synchronize.WaitFor……) 先说一下RTL和VCL RTL(Run-Time library ...

  10. NSUserDefault -- synchronize 浅析

    NSUserDefault的使用比较简单:NSUserDefaults *mySettingData = [NSUserDefaults standardUserDefaults];  创建NSUse ...

随机推荐

  1. MongoDB安装启动教程

    MongoDB安装启动教程 简易教程:鉴于第一次大家使用分布式数据库,提供一个简易教程(也可看老师的PPT或者视频) 1.点击安装包(老师给的),安装目录不要更改,否则后面配置需要改,可能导致装不上 ...

  2. Alpha项目测试--个人第五次博客

    第五次个人博客--测试 这个作业属于哪个课程 系统分析与设计 这个作业的要求在哪里 Alpha项目测试 团队名称 西柚排课王 这个作业的目标 测试别人的项目,从客观的角度体验项目 一.测试项目一 团队 ...

  3. BigDecimal加减乘除计算

    一.简述 java.math.BigDecimal不可变的.任意精度的有符号十进制数.BigDecimal 由任意精度的整数非标度值(unscaledValue)和32位的整数标度(scale)组成. ...

  4. flask实战-个人博客-使用工厂函数创建程序实例 --

    使用工厂函数创建程序实例 使用蓝本还有一个重要的好处,那就是允许使用工厂函数来创建程序实例.在OOP(Object-Oriented Programming,面向对象编程)中,工厂(factory)是 ...

  5. Nginx——配置文件服务下载

    前言 只是临时搭建的一个下载服务,所以就直接用nginx来咯 步骤 解析域名 将域名解析到要部署应用对应的服务器,就是个解析操作,没啥好讲的 创建目录 # mkdir /data/install/ 配 ...

  6. 开启了wpjam以后网站语言不能设置英文的解决方法

    一位网友问ytkah开启了wpjam以后网站语言不能设置英文了这是什么情况?选择English保存以后还是简体中文,禁用插件再设置语言是可以设为English,好几个站点都是这样 其实很简单,只要把这 ...

  7. 通过100张图一步步理解CNN

    https://blog.csdn.net/v_july_v/article/details/79434745 Youtube上迄今为止最好的卷积神经网络快速入门教程 https://www.bili ...

  8. (尚034)Vue_案例_数据存储优化(代码优化!!!)

    最好能将上述代码抽取成一个模块(读json数据+写json数据) 1.在src下新建文件夹util(util文件夹用于放入工具的模块) 2.*使用localStorage存储数据的工具模块* 一个模块 ...

  9. 腾讯蓝鲸cmdb源码编译

    腾讯蓝鲸 cmdb 源码编译环境依赖 环境包参考: golang >= 1.8 python >= nodejs >= (编译过程中需要可以连公网下载依赖包) Python 环境 w ...

  10. lintcode-720重排带整数字符串

    题目描述: 给一包含大写字母和整数(从 0 到 9)的字符串, 试写一函数返回有序的字母以及数字和. 样例 给出 str = AC2BEW3, 返回 ABCEW5字母按字母表的顺序排列, 接着是整数的 ...