1. Synchronized 用 过 吗 , 其 原 理 是 什 么 ?

  1. Synchronized 是 由 JVM 实 现 的 一 种 实 现 互 斥 同 步 的 一 种 方 式 , 如 果 查 看 被Synchronized 修 饰 过 的 程 序 块 编 译 后 的 字 节 码 , 会 发 现 ,被Synchronized修 饰 过 的 程 序 块 , 在 编 译 前 后 被 编 译 器 生 成 了monitorentermonitorexit 两 个 字 节 码 指 令 。
  2. monitorenter 和 monitorexit,这 两 个 指 令 是 什 么 意 思 呢 ?

在 虚 拟 机 执 行 到 monitorenter 指 令 时 , 首 先 要 尝 试 获 取 对 象 的 锁
如 果 这 个 对 象 没 有 锁 定 , 或 者 当 前 线 程 已 经 拥 有 了 这 个 对 象 的 锁 , 把 锁 的 计 数 器 +1; 当 执 行 monitorexit 指 令 时 将 锁 计 数 器 -1; 当 计 数 器 为 0 时 , 锁 就 被 释 放 了 。
如 果 获 取 对 象 失 败 了 , 那 当 前 线 程 就 要 阻 塞 等 待 , 直 到 对 象 锁 被 另 外 一 个 线 程 释 放 为 止 。
Java 中 Synchronize 通 过 在 对 象 头 设 置 标 记 , 达 到 了 获 取 锁 和 释 放 锁 的 目 的 。

2. 你 刚 才 提 到 获 取 对 象 的 锁 , 这 个 “ 锁 ” 到 底 是 什 么 ? 如 何 确 定

对 象 的 锁 ? “ 锁 ” 的 本 质 其 实 是 monitorentermonitorexit 字 节 码 指 令 的 一个 Reference 类 型 的 参 数 , 即 要 锁 定 和 解 锁 的 对 象 。 我 们 知 道 , 使 用Synchronized 可 以 修 饰 不 同 的 对 象 , 因 此 , 对 应 的 对 象 锁 可 以 这 么 确 定 。
1. 如 果 Synchronized 明 确 指 定 了 锁 对 象 , 比 如 Synchronized( 变 量 名 ) ,Synchronized(this) 等 , 说 明 加 解 锁 对 象 为 该 对 象 。
2. 如 果 没 有 明 确 指 定 :

  • 若 Synchronized 修 饰 的 方 法 为 非 静 态 方 法 , 表 示 此 方 法 对 应 的 对 象 为 锁 对 象 ;
  • 若 Synchronized 修 饰 的 方 法 为 静 态 方 法 , 则 表 示 此 方 法 对 应 的 类 对 象 为 锁 对 象 。

注 意 , 当 一 个 对 象 被 锁 住 时 , 对 象 里 面 所 有 用 Synchronized 修 饰 的 方 法 都 将 产 生 堵 塞 , 而 对 象 里 非 Synchronized 修 饰 的 方 法 可 正 常 被 调 用 , 不 受 锁 影 响 。

3. 什 么 是 可 重 入 性 , 为 什 么 说 Synchronized 是 可 重 入 锁 ?

可 重 入 性 是 锁 的 一 个 基 本 要 求 , 是 为 了 解 决 自 己 锁 死 自 己 的 情 况
比 如 下 面 的 伪 代 码 , 一 个 类 中 的 同 步 方 法 调 用 另 一 个 同 步 方 法 , 假 如
Synchronized 不 支 持 重 入 , 进 入 method2 方 法 时 当 前 线 程 获 得 锁 ,
method2 方 法 里 面 执 行 method1 时 当 前 线 程 又 要 去 尝 试 获 取 锁 , 这
时 如 果 不 支 持 重 入 , 它 就 要 等 释 放 , 把 自 己 阻 塞 , 导 致 自 己 锁 死 自 己 。
对 Synchronized 来 说 , 可 重 入 性 是 显 而 易 见 的 , 刚 才 提 到 , 在 执 行 monitorenter 指 令 时 , 如 果 这 个 对 象 没 有 锁 定 , 或 者 当 前 线 程 已 经 拥有 了 这 个 对 象 的 锁 ( 而 不 是 已 拥 有 了 锁 则 不 能 继 续 获 取 ) , 就 把 锁 的 计 数 器 +1, 其 实 本 质 上 就 通 过 这 种 方 式 实 现 了 可 重 入 性 。 (实现可重入性原理其实就是monitorenter指令【如果当前线程有了该对象的锁,或者该对象没有锁定,就把锁的计数器+1。】)