为什么要锁

当多个线程要对同一个目标进行修改的时候,为了保证数据的一致性,有序性,所以进行加锁。

通过对一个对象进行加锁,只有一个线程拿到这个对象,才能执行一段代码。

Synchronized的特性

  • 原子性
  • 可见性
    • “对一个变量unlock操作之前,必须要同步到主内存中;如果对一个变量进行lock操作,则将会清空工作内存中此变量的值,在执行引擎使用此变量前,需要重新从主内存中load操作或assign操作初始化变量值” 来保证的;

  • 但是不保证有序性

synchronized的基本知识点

  • synchronized方法的变型

synchronized关键字实际修饰的是一个Object 类,类似于synchronized(Object o), 如果直接修饰synchronized 方法,则等同于

锁的是该类的this对象。

  • package juc.sync;public class T1 {private int count = 0;private static int  count1 = 0;private Object obj = new Object();public void m() {synchronized(obj) {count++;System.out.println(Thread.currentThread().getName() + "count="+count);}}public synchronized void m1() {count++;System.out.println("等同于synchronized(this)");}public synchronized static void m2() {count1++;System.out.println("等同于synchronized(T1.class)");}public static void main(String[] args) {}}
  • 同步方法和非同步方法可否一起调用?

答案是可以,非同步方法没有任何锁,当然这段代码可以被多个线程随时访问。

package juc.sync;
//同步方法和不同步的方法可否一起调用
public class T3 {public synchronized void  m1() {try {Thread.sleep(200);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName() + "synchronized");}public void m2() {try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName() + "not synchronized");}public static void main(String[] args) {T3 t = new T3();
//   new Thread(()-> {
//       t.m1();
//   }).start();new Thread(t::m1,"t1").start();
//   new Thread(()-> {
//   t.m2();
//   }).start(); new Thread(t::m2,"t2").start();}
}
  • Synchronized可重入?

可重入的意思是一个同步方法是否可以调用另一个同步方法?可以,因为第一个方法拿的是一个对象锁,到第二方法的时候发现它也是同一把锁的话,是允许调用第二个方法的代码块的。

package juc.sync;public class T4 {synchronized void m1() {try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}m2();System.out.println(Thread.currentThread().getName() + "调用完m2");}synchronized void m2() {try {Thread.sleep(200);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName() + "m2 end");}public static void main(String[] args) {T4 t = new T4();t.m1();}
}
  • 该线程发生议程会释放锁

  • 同步队列和等待队列的区别
    • 同步队列指得是在runnable的线程,正在准备竞争锁的队列,如果锁被占用了,就会一直在同步队列里
    • 等待队列指的是在wait的线程,比如线程正在wait的,sleep的都会放到等待队列,等到被notify或者时间到了,就可以进入同步队列去竞争锁了。

JVM的锁的底层实现

hotspot的实现,是锁的对象上面有一个64位的markword,64位中的2位用来判断对象是否被锁。

JDK早期都是重量级,就是直接对OS去申请这个锁,效率非常低。

现在采取了锁升级的方法。

比如我们sync(Object o)

o上有一个markword

锁升级的过程

1)最开始Object o的时候是无锁态。

2)然后有线程A要进去,就在这个锁(门)上打上一个标记A,偏向锁,告诉这样下次线程A再进来的时候看到标记A,就可以直接进去了。也就是在markword上记录这个线程ID

3) 如果这个时候线程B再来,就要和线程A竞争锁(门),这个通过CAS的过程来竞争,就是读门上的标签,如果为空,就去把线程B的地址写到门上,但写的过程发现标签变了,就自旋等待。

4)如果自旋的线程超过一定数量,就会触发锁升级到重量级/系统锁,就全部进入锁的队列中,不再自旋等待了。

自旋锁和系统锁的选择

自旋锁是消耗CPU, 而系统锁会引起阻塞。

线程的执行时间短且线程少可以用自旋锁,否则用重量级锁

无锁CAS-> 锁的优化

CAS并不是通过加OS锁,

为了解决syncronize的性能问题,使用CAS来解决,不需要加同步锁

CAS(value, expected,NewValue)

先是判断当前读出来的value值与expected进行比较,如果相当则更新为新值V, 如果不相等,就要重新读取value值,一直等到相等的时候,更新为新值V。所以这个线程会一直自旋在那里等待着两值相等。

  • Atomic类

    • AtomicInteger类

Synchronized的前因后果相关推荐

  1. 读书|《静心冥想的练习》:体验超越一切理解的平静与快乐

    冥想是瑜伽实现入定的一项技法和途径,把心.意.灵完全专注在原始之初之中,最终目的在于把人引导到解脱的境界.瑜伽者通过冥想来制服心灵,并超脱物质欲念:感受到和原始动因直接沟通.通过简单练习冥想,即可帮助 ...

  2. 【java线程】锁机制:synchronized、Lock、Condition

    [Java线程]锁机制:synchronized.Lock.Condition 原创 2013年08月14日 17:15:55 标签:Java /多线程 74967 http://www.infoq. ...

  3. java static 可见性_Java多线程 synchronized与可见性的关系以及可见性问题总结

    作者:七里香的编程之路 出自:OSCHINA 原文:my.oschina.net/u/4098550/blog/4548274 能保证可见性的措施 除了volatile 可以让变量保证可见性外.hap ...

  4. 你真的掌握了并发编程volatile synchronized么?

    先看代码: import java.util.concurrent.atomic.AtomicInteger;/**** @author xialuomantian*/ public class Ne ...

  5. Java使用字节码和汇编语言同步分析volatile,synchronized的底层实现

    关于怎么查看字节码的五种方法参考本人另一篇文章<Java以及IDEA下查看字节码的五种方法> 查看汇编语言汇编码 说要看汇编还是很有必要的,因为有些地方比如加锁其实还是通过汇编实现的,只看 ...

  6. java并发vol_java 并发中 volitile、synchronized和lock的比较(一)

    1.volitile和(synchronnized.lock) 首先比较volitile和synchronnized,volitile线程不安全,但是synchronized则是线程安全的. voli ...

  7. synchronized底层原理_你用过synchronized吗?它的底层原理是什么?Java经典面试题来了...

    并发编程已经成为程序员必备技能 作为Java程序员,不懂得并发编程显然已经不能满足市场需求了,尤其是在面试过程中将处于被动地位,也有可能面试将就此终结. 那么作为Java开发者的你,日常虽然可以基于J ...

  8. 面试题-自旋锁,以及jvm对synchronized的优化

    背景 想要弄清楚这些问题,需要弄清楚其他的很多问题. 比如,对象,而对象本身又可以延伸出很多其他的问题. 我们平时不过只是在使用对象而已,怎么使用?就是new 对象.这只是语法层面的使用,相当于会了一 ...

  9. JAVA多线程之Synchronized、wait、notify实例讲解

    一.Synchronized synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争 ...

最新文章

  1. 数据科学家必须要掌握的5种聚类算法
  2. linux 网卡流量脚本,每5分钟统计Linux 网卡流量的脚本
  3. php获取全部post_php post获取所有提交
  4. UVa10911 Forming Quiz Teams(dp)
  5. Windows环境下spyder调用Arcpy
  6. 这份门禁系统培训PPT也太全面了,门禁系统知识,看这一篇就够了
  7. 宏碁e5572g57mx加固态_宏基e5572g57mx怎么拆机
  8. scp 安全复制(远程文件复制工具)
  9. 分享实录 | 深度学习技术红利下的代码补全
  10. 第二章:Java基本语法
  11. 浅谈MVC MVP MVVM
  12. c语言数字和字母输出的,请问这个用c怎么做:输入一串字符,分别统计其中数字和字母的个数...
  13. stack 和 heap区别
  14. 苹果发布新iPhone SE,售价3299元起;百度网盘破解者被捕;GitHub核心功能免费开放 | 极客头条...
  15. 【最短路】Walls
  16. 咖说丨破碎的互联网下,加密技术正在恢复数据主权!
  17. .NET EF(Entity Framework)详解
  18. python和java就业对比_Python,Java和JavaScript哪个更容易就业?
  19. Extending Laravel with First Party Packages 用第一方软件包扩展Laravel Lynda课程中文字幕
  20. 英语不好学java好学吗_英语不好能学好java,做程序员吗?

热门文章

  1. jwt单点登录 和防重放攻击
  2. Note For Linux By Jes(18)-X Window 配置介绍
  3. 【宋红康 MySQL数据库 】【高级篇】【03】MySQL的数据目录
  4. switch语句的执行顺序
  5. 全球与中国2,5-二甲基吡啶试剂市场现状及未来发展趋势
  6. MongoDB3:复制集
  7. 评法国和瑞士之比赛郁闷篇
  8. 六,基于FPGA的高速串行通信GTX知识梳理
  9. 王者荣耀服务器不稳定,王者荣耀延迟460?可能是这六个原因导致的
  10. 风丘科技为您提供电动汽车高压测试方案