synchronized 只看一篇就够了

这个关键字涉及的知识点比较多。这里准备从她的作用。她的使用。她的原理。以及她的兄弟姐妹四个方面来讲。
首先她的作用。
1.多线程同步里头作为 锁 能锁类。能索对象。能锁代码块
2.在synchronized包含的代码块开头跟结尾的部分加入了共享变量的数据同步,我个人认为第二条才是为啥这个关键字起名的原因。为了同步嘛。至于如何同步在使用过程中一一解析

先看常用锁的部分。

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  3. 修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

锁对象跟类 有点太抽象。换成通俗的说法。对象就是每次你new 出来的那个Object。类其实也是一个Object. 比如Integer.class。但是这类class 是单例的。就是有且只有一个。下面用实际代码来加深印象。

第一种 代码块
synchronized(XXX){
}

这里XXX 基本可以是具体的对象。 Object a=new Object(); synchronized(a){} 这种对象一旦被锁上。这个对象其他的被synchronized包含的不管是方法(要抛去static synchronized 锁的是 Object.class对象是另一个对象)还是代码块 是都进不去的。只有等待{}完成。但是如果是Object b=new Object() 是另一个对象。b的所有方法还是可以随便访问的。

如果XXX是 this这个关键字 锁的是具体的对象。还是上面那个规则。同对象就要等代码块执行完。不同对象无所谓。

如果XXX是 BBB.class 。比如

那不管是FlyweightFactory a=new FlyweightFactory(); FlyweightFactory b=new FlyweightFactory();
那不管是a.getFlyweightMapSize 还是b.getFlyweightMapSize 都会被锁。这里锁的是一个独一无二的Class对象
这个Class对象跟 this是不同的对象。所以下面的代码块是依然可以进入的。

最后看看加在静态方法上会是什么结果。锁的是类还是对象。答案是类。也就是等同于synchonized(class)。

这两个方法执行的时候 一旦有一个进入了代码块,另一个就要等代码块执行完。注意是代码块。就是{}。ok到这里使用就说完了。下面开始讲原理 synchonized究竟干了啥

这里我不想跟其他文章一样开始说什么monitor对象 java对象头 这些都是具体细节。我就想讲一个基本的实现逻辑。 这个synchonized东西是跟我们现实场景是很像的.就是去银行办理业务。你进门就要拿一个号。前面要有人你就要排队。实际上不管是她的兄弟Lock还是后面其他各种升级版本 AQS 都是这个逻辑,就是拿一个凭证进队列。没到你,你就只能等。当然为了更有效率。就有了各种锁。早期synchonized还是很慢的。但是随着jdk的升级。底层对synchonized这个做了很多优化。具体不讲了。总结一句话就是有了各种场景的判断,在不同的场景下让效率更高。因为都是底层的活这里就一一说明了。最后要讲一个synchonized 对成员变量可见性的影响 。就是 synchonized代码块里头如果用到了 成员变量或者说是共享变量。那进入的时候会强制刷新一次从共享内存到工作内存的同步。 同理,在退出的时候,会完成一次工作内存到共享内存的同步。这个到底意义何在。

一定要记住是在代码块全部完成的时候,才会同步到共享内存。比如有给boolean成员变量 一个方法是修改。一个方法是读。假如在方法执行到修改的方法执行到一半boolean 从true变成false,但是这个false是工作内存的变量值。 但是方法的因为底层调度切换到了读的方法。对不起这个读的方法因为读的还是主内存的拷贝还是ture。内存可见性问题来了。要解决这个问题咋办呢。第一种是给读写的方法都加上synchonized。有啥作用呢。就是延迟读。大家脑补一下。假如还是刚才执行到一半。但是方法还没结束。线程确实也切换了读。但是发现因为加了锁进不去方法。只能等待刚才的方法完全执行完。而方法执行完的时候工作内存已经完成了同步了。主内存的值已经变成了false。再切换到读方法的时候。因为锁解除。方法能进。第二个变量要完成一次主内存到工作内存同步。已经是false。刚才的不同步的问题就解决了。 第二种就是涉及到了volatile这个关键字。后面再讲。

最后要说说synchonized 的一些缺点。很多场景实现不了的。第一个就是我可以拿锁,但是拿不到我不想等的情况 。第二种是两个方法。对一个共享变量。这个共享变量没有别的地方独写。一读一写的情况。读的时候可以随便进。写的时候要看有没有锁。有写锁或者读锁都不能进。这两种情况synchonized 都没法实现。第三种情况 保证排队的顺序。synchonized的队列默认是非公平的。也就是排队10人。先来的未必先执行,看运气。 synchonized 会导致死锁。下面给一个最简单的死锁里头
Object a ,b

synchonized(a){
synchonized(b){
}
}

synchonized(b){
synchonized(a){
}
}

很简单。就是多个对象嵌套使用的时候。同时进a。同时进b。 a拿不到b。 b也拿不到a。 所以在有嵌套的时候要小心。

相关推荐:

详细解读java同步之synchronized解析

问题 (1)synchronized的特性? (2)synchronized的实现原理? (3)synchronized是否可重入? (4)synchronized是否是公平锁? (5)synchronized的优化? (6)synchronized的五种使用方式? 简介 synchronized关...

java同步机制及synchronized关键字的应用是怎样的

java同步机制及synchronized关键字的应用是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步...

一文让你读懂Synchronized底层实现,秒杀面试官

本文为死磕Synchronized底层实现第三篇文章,内容为轻量级锁实现。轻量级锁并不复杂,其中很多内容在偏向锁一文中已提及过,与本文内容会有部分重叠。另外轻量级锁的背景和基本流程在概论中已有讲解。强烈建议在看过两篇文章的基础下阅读本文。本系列文章将对HotSpot的synchronized锁实现进...

synchronized和ReentrantLock可重入锁验证的操作方法

今天就跟大家聊聊有关synchronized和ReentrantLock可重入锁验证的操作方法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一个线程已经获得了一把锁,则可以再多次重复获得这把已经获取的锁而不会发生死锁(可类比生活大门锁示例)。...

JAVA的synchronized作用是什么

本篇内容介绍了“JAVA的synchronized作用是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录1、synchronized的作用2、synchronized的语法3、Monitor原理...

synchronized和Lock有什么区别

这篇文章主要介绍synchronized和Lock有什么区别,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!区别:1、lock是一个接口,而synchronized是java的一个关键字。2、synchronized在发生异常时会自动释放占有的锁,因此不会出现死锁;而lock发...

Java中怎么利用synchronized关键字实现同步机制

Java中怎么利用synchronized关键字实现同步机制,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Java的synchronized使用方法总结1. 把synchronized当作函数修饰符时,示例代码如下:Publi...

JAVA中native方法与synchronized 关键字

native,synchronized[@more@]JAVA中native方法@与羊共舞的狼Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。  可以将na...