【JUC】2.synchronized
synchronized关键字的用法也不做太多笔记了,简单回顾一下;
synchronized三种使用方式:
修饰实例方法:
线程获取的是当前调用此方法的对象的对象头;即:锁是当前对象;
public synchronized void method(){ // ...
}
修饰静态方法:
线程获取的是此类的class对象,相当于synchronized(xxxx.class)
public synchronized static void test() {
// ...
}
修饰代码块:
synchronized (this){
}
synchronized (MySynchronized.class){
}
synchronized与volatile
虽然volatile可以当做是轻量级的synchronized,但是它俩还是有一定区别的,比如volatile的禁止指令重排序;
在懒加载的双重校验单例模式下,这两个关键字都不可缺少:
由于饿汉单例的资源浪费,不用也加载,懒加载就很常用;
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
//类对象加锁
synchronized (Singleton.class) {
// 这里不进行二次判断,无法实现单例
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
两个关键点:
1).为什么必须要用volatile?
new Singleton()其实是分为三步执行:
- 为 uniqueInstance 分配内存空间
- 初始化 uniqueInstance
- 将 uniqueInstance 指向分配的内存地址
但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。
例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。
使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
2)为什么双重校验?
如果没有第二次校验,一个线程在创建实例之前,另一个线已经通过了第一次校验,就会创建两个对象;
synchronized以前被称为重量级锁,效率很低;在JDK1.6之后,Java的锁优化机制,已经很丰富了,synchronized也被优化的很好了;
具体有关于锁机制,请看,个人觉得总结的还是很详细的:https://www.cnblogs.com/mussessein/p/11651148.html
【JUC】2.synchronized的更多相关文章
- 【JUC】4.Synchronized与ReentrantLock对比
与synchronized相同,ReentrantLock也是一种互斥锁: synchronized与ReentrantLock的对比: 都是可重入锁 可以再次获取自己的内部锁,即:一个线程获取某对象 ...
- 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)
一.前言 在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看Arra ...
- 【1】【JUC】JDK1.8源码分析之ArrayBlockingQueue,LinkedBlockingQueue
概要: ArrayBlockingQueue的内部是通过一个可重入锁ReentrantLock和两个Condition条件对象来实现阻塞 注意这两个Condition即ReentrantLock的Co ...
- 【1】【JUC】JDK1.8源码分析之ReentrantLock
概要: ReentrantLock类内部总共存在Sync.NonfairSync.FairSync三个类,NonfairSync与FairSync类继承自Sync类,Sync类继承自AbstractQ ...
- 【JUC】阻塞队列&生产者和消费者
阻塞队列 线程1往阻塞队列添加元素[生产者] 线程2从阻塞队列取出元素[消费者] 当队列空时,获取元素的操作会被阻塞 当队列满时,添加元素的操作会被阻塞 阻塞队列的优势:在多线程领域,发生阻塞时,线程 ...
- 【1】【JUC】Condition和生产者消费者模型
本篇文章将介绍Condition的实现原理和基本使用方法,基本过程如下: 1.Condition提供了await()方法将当前线程阻塞,并提供signal()方法支持另外一个线程将已经阻塞的线程唤醒. ...
- 【JUC】synchronizated和lock的区别&新lock的优势
原始构成 synchronized是关键字,属于JVM层面 javap -c 的结果显示 synchronized是可重入锁 11:是正常退出 17:是异常退出[保证不产生死锁和底层故障] Lock是 ...
- 【JUC】JUC锁框架综述
一.前言 在分析完了集合框架后,很有必要接着分析java并发包下面的源码,JUC(java.util.concurrent)源码也是我们学习Java迈进一步的重要过程.我们分为几个模块进行分析,首先是 ...
- 【JUC】如何理解线程池?第四种使用线程的方式
线程池的概念 线程池的主要工作的控制运行的线程的数量,处理过程种将任务放在队列,线程创建后再启动折现任务,如果线程数量超过了最大的数量,则超过部分的线程排队等待,直到其他线程执行完毕后,从队列种取出任 ...
随机推荐
- Linux记录-批量安装ssh(转载)
首先,需要检查expect是否安装:rpm -qa|grep expect 然后,在操作机上创建公钥:ssh-keygen 一路回车即可 创建好之后到/root/.ssh/下就可以看到id开头的2个文 ...
- Python - Django - 组件
网站中通常会有一个导航条,如下图 这个导航条在很多页面都会存在 可以把导航条做成一个组件,让要显示导航条的网页包含 导航条组件 nav.html: <h1>假装这是一个导航条</h1 ...
- Python使用numpy实现BP神经网络
Python使用numpy实现BP神经网络 本文完全利用numpy实现一个简单的BP神经网络,由于是做regression而不是classification,因此在这里输出层选取的激励函数就是f(x) ...
- LeetCode_278. First Bad Version
278. First Bad Version Easy You are a product manager and currently leading a team to develop a new ...
- Linux系统swappiness参数在内存与交换分区之间优化作用
http://blog.sina.com.cn/s/blog_13cc013b50102wskd.html swappiness的值的大小对如何使用swap分区是有着很大的联系的.swappiness ...
- python:如何传递一个列表参数
- 微服务Consul系列之集群搭建
在上一篇中讲解了Consul的安装.部署.基本的使用,使得大家有一个基本的了解,本节开始重点Consul集群搭建,官方推荐3-5台Server,因为在异常处理中,如果出现Leader挂了,只要有超过一 ...
- SELinux安全子系统的学习
SELinux(Security-Enhanced Linux)是美国国家安全局在 Linux 开源社区的帮助下开发的 一个强制访问控制(MAC,Mandatory Access Control)的安 ...
- Echart timeline 高级用法!!!!
一.前言 在使用 echart timeline 来着图形可视化时,我使用的和官网也不一样,因为我有使用映射关系.比如我将 no 映射到X轴,将 d4 映射到Y轴. 二.参考 echart官网:htt ...
- 史上最浅显易懂的RxJava入门教程
RxJava是一个神奇的框架,用法很简单,但内部实现有点复杂,代码逻辑有点绕.我读源码时,确实有点似懂非懂的感觉.网上关于RxJava源码分析的文章,源码贴了一大堆,代码逻辑绕来绕去的,让人看得云里雾 ...