前置知识

  • 了解Java基本语法
  • 了解多线程基本知识

知识介绍

  • Synchronized简介:作用、地位、不控制并发的后果
  • 两种用法:对象锁类锁
  • 多线程访问同步方法的7种情况:是否是static、Synchronized方法等
  • Synchronized的性质:可重入、不可中断
  • 原理:加解锁原理、可重入原理、可见性原理
  • Synchronized的缺陷:效率低、不够灵活、无法预判是否成功获取锁
  • 常见问题:
    • 如何选择Lock或Synchronized等
    • 如何提高性能、JVM如何解决那个线程获取锁等

Synchronized简介

作用

官方解释

  同步方法支持一种简单的策略来防止线程干扰和内存一致性错误:如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的。

通俗易懂的解释

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

地位

  • Synchronized是Java的关键字,被Java语言原生支持

代码演示:不使用并发手段的后果演示

代码实战:两个线程同时a++,最后结果会比预计的少

原因

  count++,它看上去只是一个操作,实际上包含了三个动作:

  1. 读取count
  2. 将count加1
  3. 将count的值写入到内存中
  • 最基本的互斥同步手段
  • 并发编程中的元老级角色,是并发编程的必学内容

Synchronized的两个用法

对象锁

  包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)

代码块形式:手动指定锁对象

方法锁形式:synchronized修饰普通方法,锁对象默认为this

类锁

概念(重要):Java类可能有很多个对象,但只有1个Class对象

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

用法和效果:类锁只能在同一时刻被一个对象拥有

形式1:synchronized加载static方法上

形式2:synchronized(*.class)代码块

消失的请求解决方案

不使用并发手段会有什么后果?如何解决?

解决问题

  两个线程同时a++,最后结果会比预计的少

原因

  count++,它看上去知识一个操作,实际上包含了三个动作

  1. 读取count
  2. 将count+1
  3. 将count的值写入到内存中

方法一

方法二

方法三

七种常见情况之123

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

  1. 两个线程同时访问一个对象的同步方法
  2. 两个线程访问的是两个对象的同步方法
  3. 两个线程访问的是synchronized的静态方法
  4. 同时访问同步方法与非同步方法
  5. 访问同一个对象的不同的普通同步方法
  6. 同时访问静态synchronized和非静态synchronized方法
  7. 方法抛异常后,会释放锁

情况一:

情况二:

情况三:

情况四:

情况五:

情况六:

情况七:

7种情况总结

3点核心思想

  1. 一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待(对应第1、5种情况)
  2. 每个实例都对应有自己的一把锁,不同实例之间互不影响;例外:锁对象锁是*.class以及Synchronized修饰的是static方法的时候,所有对象共用同一把锁(对应第2、3、4、6种情况);
  3. 无论是方法正常执行完毕或者方法抛出异常,都会释放锁(对应第7种情况)

Synchronized缺陷

  • 效率低:锁的释放情况少、试图获得锁时不能设定超时、不能中断一个正在试图获得锁的线程
  • 不够灵活(读写锁更灵活):加锁和释放的时机单一,每个锁仅有单一的条件(某个对象),可能是不够的
  • 无法知道是否成功获取到锁

常见面试问题

1、使用注意点:锁对象不能为空、作用域不宜过大、避免死锁

2、如何选择Lock和Synchronized关键字?

3、多线程访问同步方法的各种具体情况

Java 高并发之魂的更多相关文章

  1. Java高并发之锁优化

    本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 public synchronized void syncMethod(){ othercode1(); ...

  2. java高并发之线程池

    Java高并发之线程池详解   线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...

  3. java高并发之锁的使用以及原理浅析

    锁像synchronized同步块一样,是一种线程同步机制.让自Java 5开始,java.util.concurrent.locks包提供了另一种方式实现线程同步机制——Lock.那么问题来了既然都 ...

  4. 1.6 JAVA高并发之线程池

    一.JAVA高级并发 1.5JDK之后引入高级并发特性,大多数的特性在java.util.concurrent 包中,是专门用于多线程发编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发 ...

  5. Java高并发之无锁与Atomic源码分析

    目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntege ...

  6. Java高并发之线程池详解

    线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对象, 那么系统效率将大大提升. ...

  7. Java高并发之设计模式

    本文主要讲解几种常见并行模式, 具体目录结构如下图. 单例 单例是最常见的一种设计模式, 一般用于全局对象管理, 比如xml配置读写之类的. 一般分为懒汉式, 饿汉式. 懒汉式: 方法上加synchr ...

  8. Java高并发之线程基本操作

    结合上一篇同步异步,这篇理解线程操作. 1.新建线程.不止thread和runnable,Callable和Future了解一下 package com.thread; import java.tex ...

  9. Java高并发之同步异步

    1.概念理解: 2.同步的解决方案: 1).基于代码 synchronized 关键字 修饰普通方法:作用于当前实例加锁,进入同步代码前要获得当前实例的锁. 修饰静态方法:作用于当前类对象加锁,进入同 ...

随机推荐

  1. vue使用readAsDataURL实现选择图片文件后预览

    vue实现选择图片文件后预览 利用h5的api可以实现选择文件并实现预览 readAsDataURL 方法会读取指定的 Blob 或 File 对象.读取操作完成的时候,readyState 会变成已 ...

  2. SSM框架手动实现分页逻辑(非PageHelper)

    第一种方法:查询出所有数据再分页 分析: 分页时,需要获得前台传来的两个参数,分别为pageNo(第几页数据),pageSize(每页的条数); 根据这两个参数来计算出前端需要的数据是查出数据list ...

  3. <反向传播(backprop)>梯度下降法gradient descent的发展历史与各版本

    梯度下降法作为一种反向传播算法最早在上世纪由geoffrey hinton等人提出并被广泛接受.最早GD由很多研究团队各自发表,可他们大多无人问津,而hinton做的研究完整表述了GD方法,同时hin ...

  4. 前后端分离————VUE+node(express)

    前后端分离----VUE+node(express) vue作为前端的框架,node(express)作为后端的框架.无数据库,使用端口保存数据. VUE: 使用vue-cli构建vue项目(vuea ...

  5. 年薪500K工程师告诉你,python都能用来做什么?

    一提到python,大家脑袋中都会想到「数据分析」.「爬虫」.「人工智能」这些词. 其实python并没有像如上所说的这样「专业」.「高深」的应用,对于初学者来说更是可以从一些超简单又有趣的小项目开始 ...

  6. maven web项目下mybatis generator的使用

    idea中新建maven web项目,完善java,resources目录: pom.xml中添加jdbc依赖,mybatis generator的依赖和插件: <dependencies> ...

  7. centos 7安装rac 11gR2时运行root.sh报错找不到ohas服务(ohasd failed to start)

    单独在linux 7中为ohasd设置一个服务.步骤如下1. 创建服务ohas.service的服务文件并赋予权限touch /usr/lib/systemd/system/ohas.servicec ...

  8. .net mvc web api Autofac依赖注入框架-戈多编程

    今天自己搭了一套基于三层的依赖注入mvc web api 的依赖注入框架,在此总结下相关配置 1.设置应用程序的.net Framework版本为 4.5 2.通过Nuget 安装autofac包 I ...

  9. 题解:2018级算法第二次上机 Zexal的竞赛

    题目描述: 样例: 实现解释: 一道需要一点思考的动态规划题目 知识点:动态规划,数据记录 首先将题目描述调整:分别输入不同分数的题目总分(便于后续计算),当获得了i分数的总分后无法获得i-1和i+1 ...

  10. Error response from daemon: Get https://registry-1.docker.io/v2/library/nginx/manifests/1.14-alpine: Get https://auth.docker.io/token?scope=repository%3Alibrary%2Fnginx%3Apull&service=registry.docker.

    docker pull 镜像时报错: Error response from daemon: Get https://registry-1.docker.io/v2/library/nginx/man ...