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

了解 JVM 鎖優化

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

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]刪除
最新教學 更多>
  • 如何有效地選擇熊貓數據框中的列?
    如何有效地選擇熊貓數據框中的列?
    在處理數據操作任務時,在Pandas DataFrames 中選擇列時,選擇特定列的必要條件是必要的。在Pandas中,選擇列的各種選項。 選項1:使用列名 如果已知列索引,請使用ILOC函數選擇它們。請注意,python索引基於零。 df1 = df.iloc [:,0:2]#使用索引0和1 ...
    程式設計 發佈於2025-07-12
  • 如何實時捕獲和流媒體以進行聊天機器人命令執行?
    如何實時捕獲和流媒體以進行聊天機器人命令執行?
    在開發能夠執行命令的chatbots的領域中,實時從命令執行實時捕獲Stdout,一個常見的需求是能夠檢索和顯示標準輸出(stdout)在cath cath cant cant cant cant cant cant cant cant interfaces in Chate cant inter...
    程式設計 發佈於2025-07-12
  • 為什麼儘管有效代碼,為什麼在PHP中捕獲輸入?
    為什麼儘管有效代碼,為什麼在PHP中捕獲輸入?
    在php ;?>" method="post">The intention is to capture the input from the text box and display it when the submit button is clicked.但是,輸出...
    程式設計 發佈於2025-07-12
  • Java是否允許多種返回類型:仔細研究通用方法?
    Java是否允許多種返回類型:仔細研究通用方法?
    在Java中的多個返回類型:一種誤解類型:在Java編程中揭示,在Java編程中,Peculiar方法簽名可能會出現,可能會出現,使開發人員陷入困境,使開發人員陷入困境。 getResult(string s); ,其中foo是自定義類。該方法聲明似乎擁有兩種返回類型:列表和E。但這確實是如此嗎...
    程式設計 發佈於2025-07-12
  • 您如何在Laravel Blade模板中定義變量?
    您如何在Laravel Blade模板中定義變量?
    在Laravel Blade模板中使用Elegance 在blade模板中如何分配變量對於存儲以後使用的數據至關重要。在使用“ {{}}”分配變量的同時,它可能並不總是最優雅的解決方案。 幸運的是,Blade通過@php Directive提供了更優雅的方法: $ old_section =...
    程式設計 發佈於2025-07-12
  • 大批
    大批
    [2 數組是對象,因此它們在JS中也具有方法。 切片(開始):在新數組中提取部分數組,而無需突變原始數組。 令ARR = ['a','b','c','d','e']; // USECASE:提取直到索引作...
    程式設計 發佈於2025-07-12
  • 如何有效地轉換PHP中的時區?
    如何有效地轉換PHP中的時區?
    在PHP 利用dateTime對象和functions DateTime對象及其相應的功能別名為時區轉換提供方便的方法。例如: //定義用戶的時區 date_default_timezone_set('歐洲/倫敦'); //創建DateTime對象 $ dateTime = ne...
    程式設計 發佈於2025-07-12
  • 如何使用不同數量列的聯合數據庫表?
    如何使用不同數量列的聯合數據庫表?
    合併列數不同的表 當嘗試合併列數不同的數據庫表時,可能會遇到挑戰。一種直接的方法是在列數較少的表中,為缺失的列追加空值。 例如,考慮兩個表,表 A 和表 B,其中表 A 的列數多於表 B。為了合併這些表,同時處理表 B 中缺失的列,請按照以下步驟操作: 確定表 B 中缺失的列,並將它們添加到表的...
    程式設計 發佈於2025-07-12
  • 如何將PANDAS DataFrame列轉換為DateTime格式並按日期過濾?
    如何將PANDAS DataFrame列轉換為DateTime格式並按日期過濾?
    Transform Pandas DataFrame Column to DateTime FormatScenario:Data within a Pandas DataFrame often exists in various formats, including strings.使用時間數據時...
    程式設計 發佈於2025-07-12
  • 如何使用FormData()處理多個文件上傳?
    如何使用FormData()處理多個文件上傳?
    )處理多個文件輸入時,通常需要處理多個文件上傳時,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    程式設計 發佈於2025-07-12
  • HTML格式標籤
    HTML格式標籤
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    程式設計 發佈於2025-07-12
  • 如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    為有效的slug生成首先,該函數用指定的分隔符替換所有非字母或數字字符。此步驟可確保slug遵守URL慣例。隨後,它採用ICONV函數將文本簡化為us-ascii兼容格式,從而允許更廣泛的字符集合兼容性。 接下來,該函數使用正則表達式刪除了不需要的字符,例如特殊字符和空格。此步驟可確保slug僅包...
    程式設計 發佈於2025-07-12
  • 如何使用Python的請求和假用戶代理繞過網站塊?
    如何使用Python的請求和假用戶代理繞過網站塊?
    如何使用Python的請求模擬瀏覽器行為,以及偽造的用戶代理提供了一個用戶 - 代理標頭一個有效方法是提供有效的用戶式header,以提供有效的用戶 - 設置,該標題可以通過browser和Acterner Systems the equestersystermery和操作系統。通過模仿像Chro...
    程式設計 發佈於2025-07-12
  • CSS強類型語言解析
    CSS強類型語言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    程式設計 發佈於2025-07-12
  • 反射動態實現Go接口用於RPC方法探索
    反射動態實現Go接口用於RPC方法探索
    在GO 使用反射來實現定義RPC式方法的界面。例如,考慮一個接口,例如:鍵入myService接口{ 登錄(用戶名,密碼字符串)(sessionId int,錯誤錯誤) helloworld(sessionid int)(hi String,錯誤錯誤) } 替代方案而不是依靠反射...
    程式設計 發佈於2025-07-12

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

Copyright© 2022 湘ICP备2022001581号-3