专栏首页老男孩成长之路一文看透Java高并发:Synchronized锁的性质、原理及其缺陷

一文看透Java高并发:Synchronized锁的性质、原理及其缺陷

前置知识

  • 了解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、多线程访问同步方法的各种具体情况

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一文读懂什么是进程、线程、协程

    我们都知道计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,统领整个计算机硬件;应用程序则是具有某种...

    Java_老男孩
  • 被开发者抛弃的 Executors,错在哪儿?

    在 Java 领域内,我们使用多线程的方式来实现并发编程。而线程本身是操作系统的一个概念,虽然不同的语言对线程都进行了一些封装,但是最终都是调用到操作系统中去创...

    Java_老男孩
  • 别翻了,这篇文章就是要让你搞定java多线程!

    由于并发肯定涉及到多线程,因此在进入并发编程主题之前,我们先来了解一下进程和线程的由来,这对后面对并发编程的理解将会有很大的帮助。

    Java_老男孩
  • Java多线程学习 (一)

    进程是操作系统运行程序的基本单位,是一次程序的执行。简单来说一个进程就是一个运行中的程序。

    小森啦啦啦
  • ThreadPoolExcutor 线程池 异常处理 (上篇)

    最近看到crossoverJie的一篇文章:一个线程罢工的诡异事件 首先感谢原作者的分享,自己获益匪浅。然后是回想到自己的一次面试经历,面试官提问了线程池中的...

    一枝花算不算浪漫
  • 如何手动实现一个 UIScrollView

    UIKit 坐标系每一个 View 都定义了他自己的坐标系,如下图所示,x 轴指向右方,y 轴指向下方:

    s_在路上
  • JVM(2): 逃逸分析和内存分配

    我们都知道Java对象都是分配在在堆上的,在过往的认识中,一直是以这样的方式存在的,但是从Java7开始支持对象的栈分配和逃逸分析机制。

    yiduwangkai
  • TiDB 在株式会社 FUNYOURS JAPAN 的应用

    株式会社 FUNYOURS JAPAN 自 2014 在日本成立以来,营运多款颇受好评的页游跟手游,如:剣戟のソティラス、九十九姬 等,对于营运游戏来说,能够了...

    PingCAP
  • 竟态条件 racing condition

    多个线程读时,线程是安全的。 当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。 我的理解,竞态条件就是一种情况。

    潇洒
  • 竞态条件 racing condition

    多个线程读时,线程是安全的。 当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。 我的理解,竞态条件就是一种情况。

    潇洒

扫码关注云+社区

领取腾讯云代金券