synchronized关键字  

  synchronized关键字最主要的三种使用方式的总结

  1.修饰实例方法,作用于当前对象实例加锁,进入同步代码块前要获得当前对象实例的锁

  2.修饰静态方法,作用于当前类对象加锁,进入同步代码块前要获得当前类对象的锁。也就是给当前类加锁,会作用于类的所有对象实例,因为静态成员不属于任何一个实例

  对象,是类成员(static表明这是该类的一个静态资源,不管new了多少个对象,只有这一份),如果一个线程A调用一个实例对象的非静态synchronized方法,而线程B调用

  这个实例对象所属类的静态synchronized方法,是允许的,不会发生互斥现象。因为访问静态的synchronized方法占用的锁是当前类的锁,访问非静态的synchronized方法

  占用的锁是当前实例对象的锁。

  3.修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码块前要获得给定对象的锁。和synchronized方法一样,synchronized(this)代码块也是锁定当前对象的。

  synchronized关键字加到static方法和synchronized(class)代码块上都是都是给class类上锁。再提一下,synchronized关键字非静态方法上是给当前对象实例加锁,另外需要

  注意的是,尽量不要使用synchronized(String a)因为JVM中字符串常量池具有缓冲功能。

  双重校验锁实现对象单例

public class Singleton {

    private volatile static Singleton singleton;

    private Singleton(){}

    public static Singleton getSingleton(){
if (singleton==null){
synchronized (Singleton.class){
if (singleton==null){
singleton = new Singleton();
}
}
}
return singleton;
}
}

  需要注意的是singleton对象使用volatile关键字修饰原因如下:

  singleton = new Singleton(); 这段代码其实分为三步执行,第一步为singleton分配内存空间,第二步初始化singleton,第三部将singleton指向分配的内存地址,但是由于

  JVM具有指令重排的特征,执行顺序有可能变成第一步->第三步->第二步,此指令重排在单线程环境下没有问题,但是在多线程环境下会导致某个线程获得还没有初始化

  的实例。例如线程1执行了第一步和第三步,此时线程2调用getSingleton()方法发现singleton并不为空,因此返回singleton,但此时singleton还未初始化。使用volatile

  关键字可以禁止JVM的指令重排,保证在多线程环境下正常运行。

  synchronized关键字和volatile关键字的区别

  把变量声明为volatile,当一个线程在工作内存中修改该变量的值之后会立即将值同步到主内存,同时使其他线程的工作内存缓存的原始值无效,另一个线程需要使用

  这个变量时,需要重新从主内存读取该变量值到自己的工作内存,保证了变量的可见性,还有一个作用是防止指令重排序。

  区别有以下几点:

    1.volatile关键字是线程同步的轻量级实现,所以volatile关键字的性能肯定要比synchronized关键字要好,但是volatile关键字只能用于变量,而synchronized关键字可以

    修饰方法和代码块。在JDK1.6之后进行了获得锁和释放锁带来的性能消耗的优化,相对来说synchronized关键字使用场景较多一点

    2.多线程访问volatile关键字不会发生阻塞,synchronized可能会发生阻塞

    3.volatile关键字能保证数据的可见性,但不能保证数据的原子性,synchronized关键字两者都能保证

    4.volatile关键字主要用于解决变量在多个线程之间的可见性,synchronized关键字解决的是多个线程之间访问资源的同步性

  

并发编程之synchronized关键字的更多相关文章

  1. Java并发编程之synchronized关键字

    整理一下synchronized关键字相关的知识点. 在多线程并发编程中synchronized扮演着相当重要的角色,synchronized关键字是用来控制线程同步的,可以保证在同一个时刻,只有一个 ...

  2. Java 多线程并发编程之 Synchronized 关键字

    synchronized 关键字解析 同步锁依赖于对象,每个对象都有一个同步锁. 现有一成员变量 Test,当线程 A 调用 Test 的 synchronized 方法,线程 A 获得 Test 的 ...

  3. 高并发编程之synchronized

    一.什么是线程? 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成.另外,线程 ...

  4. Java并发编程之volatile关键字解析

    一内存模型的相关概念 二并发编程中的三个概念 三Java内存模型 四深入剖析volatile关键字 五使用volatile关键字的场景 volatile这个关键字可能很多朋友都听说过,或许也都用过.在 ...

  5. 并发编程之synchronized锁(一)

    一.设计同步器的意义 多线程编程中,有可能会出现多个线程同时访问同一个共享.可变资源的情况,这个资源我们称之其为临界资源:这种资源可能是:对象.变量.文件等. 共享:资源可以由多个线程同时访问 可变: ...

  6. Java并发编程之volatile关键字

    大概是因为项目.业务的原因,工作上几乎还没有使用过多线程相关的功能,相关知识差不多都忘了,所以最近补一下基础. volatile用来修饰共享变量,volatile变量具有 synchronized 的 ...

  7. Java 并发编程之volatile关键字解析

    摘录 1. 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于CPU执 ...

  8. Java并发编程之synchronized

    在Java编程中,为了保证线程安全,有3种不同的思路1.互斥同步:包括synchronized和lock等. 2.非阻塞同步:如AtomicInteger的increaseAndGet()方法等. 3 ...

  9. 并发编程之synchronized(二)------jvm对synchronized的优化

    一.锁的粗化 看如下代码 public class Test { StringBuffer stb = new StringBuffer(); public void test1(){ //jvm的优 ...

随机推荐

  1. Spark分布式编程之全局变量专题【共享变量】

    转载自:http://www.aboutyun.com/thread-19652-1-1.html 问题导读 1.spark共享变量的作用是什么?2.什么情况下使用共享变量?3.如何在程序中使用共享变 ...

  2. [ZZ] matlab中小波变换函数dwt2和wavedec2 系数提取函数appcoef2和detcoef2

    https://zhidao.baidu.com/question/88038464.html DWT2是二维单尺度小波变换,其可以通过指定小波或者分解滤波器进行二维单尺度小波分解. 而WAVEDEC ...

  3. WebService之客户端

    创建项目 File→New→Other→Web Services→Web Service Client中输入从服务端得到的wsdl链接: http://localhost:8080/WS_WebSer ...

  4. Kettle解决方案: 第三章 安装和配置

  5. mysql 设置初始密码

    mysqladmin -uroot password "123" 设置初始密码 由于原密码为空,因此-p可以不用 mysqladmin -uroot -p"123&quo ...

  6. verilog 中task用法

    1.任务定义  任务定义的形式如下:  task task_id;      [declaration]      procedural_statement  endtask  其中,关键词 task ...

  7. JSP——文件上传

    Web应用中,文件的上传是很常见的功能,今天在此记录下所学的感悟吧. 实现Web应用中文件的上传需要用到的核心组件是Commen-fileUpload,组件, 但还需要Common-IO组件的支持.可 ...

  8. linux操作系统中安装redis

    第一步:安装gcc编译软件 redis是用c编写的,在下载之后需要使用gcc编译之后才能安装,首先需要下载gcc yum install gcc-c++ 第二步   下载redis安装包,并解压编译 ...

  9. php 操作mysql

    //由于前期数据库字段设计问题,没太注意,字段内容,后台python采集数据直接插入,没做处理,数据又不想丢掉,只能对网站数据库字段内容进行处理,100万条数据,调试了半天,很多思路都试过,各种坑,弄 ...

  10. springboot学习一:快速搭建springboot项目

    1.idea创建springboot工程 JDK选择1.8以上的版本 选择springboot的版本和添加配置项 新建一个HelloController,测试 访问 http://localhost: ...