」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 了解 JVM 鎖優化

了解 JVM 鎖優化

發佈於2024-11-08
瀏覽:550

Understanding JVM Lock Optimizations

并发对于开发可以执行多个并发操作的健壮、可扩展的应用程序非常关键。然而,为此需要付出同步方面的代价。由于获取和释放锁的随之而来的开销,它会产生性能成本。为了减轻这些性能成本,JVM 中融入了多种优化,例如偏向锁定、锁定消除、锁定粗化以及轻量级和重量级锁定的概念。

在本文中,我们将更详细地了解这些优化,并探讨它们如何改进多线程 Java 应用程序中的同步。

Java 锁定基础知识

在Java中,块或方法的同步确保一次只有一个线程可以执行代码的关键部分。当考虑多线程环境中的资源共享时,这一点尤其重要。 Java 通过依赖内在锁来实现这一点,或者有时,它们被称为与对象或类关联的监视器,通过使用同步块来帮助管理对线程的访问。

虽然同步是线程安全的必要条件,但当争用较低或完全不存在时,同步的成本可能会相当高。这就是 JVM 优化介入的地方。因此,这降低了锁定成本并提高整体性能。

1。偏向锁定

什么是偏向锁定?

偏向锁是一种旨在减少锁获取开销的优化。它进行了优化,以降低锁获取的成本,锁获取的成本由单个线程主导或大部分由单个线程访问。此类程序通常由同一线程获取和释放锁,而不会与其他线程发生争用。 JVM 可以识别这种模式并将锁偏向于该特定线程;接下来的锁获取几乎是免费的。

偏向锁定如何工作?

如果启用偏向锁定,那么当线程第一次获取锁时,它会使该锁偏向于该线程。线程的身份记录在锁对象的标头中,该线程后续的锁获取不涉及任何同步 - 它们只是检查锁是否偏向当前线程,这是一个非常快速的非阻塞操作.

如果另一个线程尝试获取锁,那么偏向就会被取消,JVM 会退回到标准的无偏锁机制。在此阶段,它现在是一个标准锁,第二个线程必须通过标准锁定过程来获取它。
偏向锁定的好处

性能:同一个线程在偏向锁上的获取几乎是免费锁的获取。

因此,不需要争用处理,因为其他线程没有机会参与获取锁。

较低的开销: 除非发生争用,否则不需要更改锁的状态或修改与同步相关的元数据。 
 

何时使用偏向锁定?

偏向锁在锁主要由同一线程访问的应用程序中很有用,例如单线程应用程序或多线程下锁争用较低的应用程序。它在大多数 JVM 中默认启用。

如何禁用偏向锁定

偏向锁定默认启用,但也可以使用 JVM 标志禁用,如下所示:

-XX:-UseBiasedLocking

2.锁定消除

什么是锁消除?

锁消除是一种非常强大的优化,JVM 完全消除了一些不必要的同步(锁)。它将在 JIT 编译期间检查代码是否有任何机会,其中发现同步是不必要的。当锁仅被一个线程访问时,或者 JVM 将用于同步的对象在不同线程中不共享同一对象时,通常会发生这种情况。一旦 JVM 认为不再需要它,它就会消除锁。

锁消除是如何工作的?

在JIT编译的逃逸分析阶段,JVM检查对象是否仅限于单个线程或仅在本地上下文中使用。如果因为对象没有逃逸创建它的线程的范围而可以删除该对象上的同步,那么情况就会如此。

例如,如果一个对象完全在一个方法中创建和使用(并且不在线程之间共享),那么 JVM 就会意识到没有其他线程可以访问该对象,因此所有同步都是多余的。在这种情况下,JIT 编译器只是完全消除锁。

零锁定开销:消除不必要的同步也将阻止 JVM 首先支付获取和释放锁的成本。

更高的吞吐量:死同步有时会导致应用程序更高的吞吐量,特别是当代码包含许多同步块时。

看一下这段代码:

public void someMethod() {
    StringBuilder sb = new StringBuilder();
    synchronized (sb) {
        sb.append("Hello");
        sb.append("World");
    }
}

在这种情况下,sb 上的同步是不必要的,因为 StringBuilder 仅在 someMethod 中使用,并且不在其他线程之间共享。通过查看这个,JVM可以执行逃逸分析来移除锁。

3.锁定粗化

什么是锁粗化?

锁粗化是一种优化,其中 JVM 扩展锁的范围以覆盖更多代码块,而不是在循环或小部分代码中连续获取和释放锁。

锁定粗化工作

如果 JVM 发现紧密循环或多个相邻代码块过于频繁地获取和释放锁,它可以通过在循环外或跨多个代码块获取锁来粗化锁。这使得重复获取和释放无锁变得昂贵,并使线程能够持有锁以进行更多迭代。

代码示例:锁定粗化

考虑这个代码片段:

for (int i = 0; i 



锁粗化将锁获取推到循环之外,因此线程仅获取锁一次:

synchronized (lock) {
  for (int i = 0; i 



JVM 可以通过避免更多的锁获取和释放来显着提高性能。

锁定粗化的好处

更少的锁定自由度开销:粗化可以避免锁的获取和释放,特别是在热点代码中,例如已经迭代了数千次的循环。

性能改进:
与不加锁、多次获取和释放此类锁的情况相比,较长时间的锁定可以提高性能。

4。轻型和重型锁

JVM 根据线程之间的争用程度使用两种不同的锁定技术。此类技术包括轻量级锁和重量级锁。

轻量级锁定

轻量级锁定发生在没有争用锁的情况下,这意味着只有一个线程试图获取该锁。在这种情况下,JVM 在尝试获取锁时会使用 CAS 操作来优化获取,这可能在没有重量级同步的情况下发生。

重量级锁定

如果多个线程想要获得同一个锁;也就是说,存在争用,JVM 将其升级为重量级锁定。这将涉及在操作系统级别阻塞线程并使用操作系统级别同步原语来管理它们。重量级锁速度较慢,因为它们实际上需要操作系统执行上下文切换以及管理线程。

锁定升级

如果轻量级锁出现争用,JVM 可能会将其升级为重量级锁。这里的升级意味着从快速的用户级锁切换到更昂贵的操作系统级锁,其中包括线程阻塞。

轻量级锁的好处

快速获取锁:在没有争用的情况下,轻量级锁比重量级锁快得多,因为它们避免了操作系统级同步。

减少阻塞:在没有争用的情况下,线程不会阻塞并以较低的延迟线性增加。

重量级锁的缺点

性能开销:重量级锁会产生线程阻塞、上下文切换和唤醒线程的成本,在非常高的争用情况下性能会下降。

所有这些优化都有助于 JVM 提高多线程应用程序的性能,因此开发人员现在可以编写安全的并发代码,而无需牺牲太多同步开销。了解这些优化可以帮助开发人员设计更高效的系统,特别是在因锁定而导致高性能损失的情况下。

版本聲明 本文轉載於:https://dev.to/arashariani/understanding-jvm-lock-optimizations-4l5i?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 了解 JavaScript 中底線 (`_`) 的使用
    了解 JavaScript 中底線 (`_`) 的使用
    在 JavaScript 中編碼時,您可能會遇到用作變數名稱的下劃線字元 (_),特別是在函數參數中。雖然乍看之下似乎很不尋常,但由於各種原因,這種做法在開發人員中很常見。在這篇文章中,我們將探討底線代表什麼,為什麼要使用它,以及它在現實範例中的顯示方式,例如 coalesceES6 函數。 ...
    程式設計 發佈於2024-11-08
  • 像程式設計師一樣思考:學習 C 基礎知識
    像程式設計師一樣思考:學習 C 基礎知識
    以程式設計師思考學習 C 語言:基本語法:變數、資料型態、常數、運算子、控制流。實戰案例:計算兩個數的平均值,輸入兩個整數並計算其平均值。 以程式設計師思考:用C 語言學習基礎引言學習程式設計並不難,尤其是當你以程式設計師思維思考時。本文將從基礎開始,用 C 語言引導你逐步了解程式設計入門知識。 C...
    程式設計 發佈於2024-11-08
  • Python 中的列表理解語法何時需要三元運算子?
    Python 中的列表理解語法何時需要三元運算子?
    列表理解難題:可迭代物件中的條件篩選在Python 中,列表理解提供了一種基於現有可迭代物件建立清單的簡潔方法。然而,出現了一個關於涉及 if 語句的列表理解的問題。 目標是比較兩個可迭代物件 a 和 b,並僅列印兩者中出現的元素。預期的程式碼如下所示:print([y if y not in b ...
    程式設計 發佈於2024-11-08
  • 使用 MetaTrader 訂單管理和市場資料收集進行自動交易
    使用 MetaTrader 訂單管理和市場資料收集進行自動交易
    Your AsimovMT class provides a comprehensive interface for interacting with MetaTrader5 (MT5) using Python. However, there are several areas in your c...
    程式設計 發佈於2024-11-08
  • Python 清單的最大大小是多少以及它如何影響功能?
    Python 清單的最大大小是多少以及它如何影響功能?
    Python列表的最大大小:綜合分析在Python中,列表是基本的資料結構,可以容納多個不同類型的元素。它們的多功能性和靈活性使得了解它們的局限性至關重要,特別是在處理大型數據集時。本文探討了 Python 清單可以達到的最大大小及其對其功能的影響。 最大清單大小Python 清單的最大大小已定義通...
    程式設計 發佈於2024-11-08
  • 託管平台清單:綜合指南
    託管平台清單:綜合指南
    在數位時代,可靠的託管平台對於任何線上展示都至關重要,無論是個人部落格、電子商務網站還是公司網站。有無數的選項可供選擇,選擇合適的託管平台可能會令人畏懼。本指南將幫助您瀏覽當今一些最好的託管平台,比較它們的功能、價格和對不同需求的適用性。 1. 藍色主機 概述:Bluehost 是...
    程式設計 發佈於2024-11-08
  • 在瀏覽器中將影片壓縮為 webm
    在瀏覽器中將影片壓縮為 webm
    ?增強您的網路影片:使用 React 將 MP4 壓縮為 WebM 工作中沒有任何有趣的事情感到無聊嗎?好吧,就在那時我決定抓緊時間修補瀏覽器 API 的當前狀態。我們可以直接透過 Web API 壓縮影片嗎?在這篇部落格中,我將向您展示如何使用現代瀏覽器功能將 MP4 影片壓縮為...
    程式設計 發佈於2024-11-08
  • 現代 PHP 中的 PHP Fiber 並發性
    現代 PHP 中的 PHP Fiber 並發性
    PHP Fibers 在 PHP 8.1 中引入,帶來了一種令人興奮的新方法來處理 PHP 中的並發和非同步程式設計。纖維可讓您在執行過程中暫停和恢復函數,使開發人員能夠更好地控制非阻塞操作,例如處理 I/O、資料庫查詢或 HTTP 請求,而無需停止整個腳本。 在本部落格中,我們將探討 PHP 纖...
    程式設計 發佈於2024-11-08
  • Laravel 的新時代:Accel 的百萬美元 A 輪融資——這就是為什麼它改變了遊戲規則!
    Laravel 的新時代:Accel 的百萬美元 A 輪融資——這就是為什麼它改變了遊戲規則!
    各位,请戴好帽子! Laravel 刚刚发布了一些激动人心的消息,震惊了开发界——由 Accel 领投的 A 轮融资 5700 万美元。作为一名热情的 Laravel 用户和企业家同事,这一公告在整个 PHP 社区引起了震动,我感到非常兴奋!那么,让我们来分析一下为什么这项投资意义重大,以及为什么 ...
    程式設計 發佈於2024-11-08
  • C++11 的 `string::c_str()` 仍然以 Null 終止嗎?
    C++11 的 `string::c_str()` 仍然以 Null 終止嗎?
    C 11 的 string::c_str() 是否消除空終止? 在 C 11 中,string::c_str 不再保證產生一個以 null 結尾的字串。 原因:在C 11 中,string::c_str 的定義與string::data 相同,而string::data 又被定義相當於*( begi...
    程式設計 發佈於2024-11-08
  • 資料分析師清單
    資料分析師清單
    SQL 清單 Excel女士清單 Power BI 清單 Tableau 清單 Python 清單 請關注此 WhatsApp 頻道以獲取更多資源
    程式設計 發佈於2024-11-08
  • 如何在 Go 中將 YAML 欄位動態解析為有限結構集?
    如何在 Go 中將 YAML 欄位動態解析為有限結構集?
    在 Go 中將 YAML 欄位動態解析為有限結構體集簡介在 Go 中將 YAML 解析為結構體非常簡單。但是,當 YAML 欄位可以表示多個可能的結構時,任務就會變得更加複雜。本文探討了使用 Go 的 YAML 套件的動態方法。 使用 YAML v2 進行動態解組對於 Yaml v2,可以使用以下方...
    程式設計 發佈於2024-11-08
  • 為什麼我的 C++ 程式碼中會出現「vtable」和「typeinfo」未定義符號錯誤?
    為什麼我的 C++ 程式碼中會出現「vtable」和「typeinfo」未定義符號錯誤?
    未定義的符號:「vtable」和「typeinfo」在提供的程式碼中,出現連結錯誤並顯示下列訊息: Undefined symbols: "vtable for Obstacle", referenced from: Obstacle::Obstacle()in ...
    程式設計 發佈於2024-11-08
  • 如何在 Python 中執行指數和對數曲線擬合?
    如何在 Python 中執行指數和對數曲線擬合?
    曲線擬合:Python 中的指數和對數方法雖然Python 中可以使用polyfit() 輕鬆進行多項式曲線擬合,但本指南探討了指數和對數曲線的方法擬合。 對數擬合擬合 y 形式的直線= A B log x,只需執行 y 對 log x 的多項式擬合。 import numpy as np x = ...
    程式設計 發佈於2024-11-08
  • 大批
    大批
    方法是可以在物件上呼叫的 fns 數組是對象,因此它們在 JS 中也有方法。 slice(begin):將陣列的一部分提取到新數組中,而不改變原始數組。 let arr = ['a','b','c','d','e']; // Usecase: Extract till index ...
    程式設計 發佈於2024-11-08

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3