簡體   English   中英

如何在 Spring MVC 控制器中使用 @PathVariable 創建同步塊?

[英]How to create a synchronize block using a @PathVariable in a Spring MVC controller?

我需要在 Spring MVC 控制器中創建一個同步塊,我想在其中使用 @PathVariable 作為我的同步對象。

@RequestMapping(value = "/upload/{providerId}/{contractId}", method = RequestMethod.POST, headers = "content-type!=multipart/form-data")
public void uploadChunked(
        @PathVariable final long providerId,
        @PathVariable final Long contractId ) {

    Attachment attachment = new Attachment();

    // store the attachment
    synchronized( contractId ){
        contractService.addAttachment( providerId, contractId, attachment );
    }
}

我將contractId自動裝箱為Long並將其用於同步對象,但是如果我在其他地方針對自動裝箱 Long 創建另一個同步塊,則同步自動裝箱值可能會成為問題。 根據JLS 5.1.7

理想情況下,裝箱給定的原始值 p 總是會產生相同的引用。 實際上,使用現有的實現技術這可能是不可行的。

因此,該塊可能正在等待盒裝 Long 上完全不相關的同步塊完成,這是不可接受的。

但是,鑒於控制器本質上是一個單例,我如何安全地與 contractId 同步? 需要明確的是,只有對具有相同contractId此方法的調用必須同步 - 具有不同contractId的調用可以同時運行。

我一直無法找到任何提供這種簡單支持的現有庫。 除了創建我自己的 util lib/class(例如:通過contractId存儲鎖定對象的靜態並發哈希圖),還有其他更簡潔的解決方案嗎?

正如您所建議的,您不能依賴原始包裝器類型來同步這些值。 一種可能的解決方案是維護一個ConcurrentHashMap ,您putIfAbsent在其中使用您的contractId作為鍵putIfAbsent一個新的鎖對象。 如果該方法返回一個對象,則鎖定該對象。 如果沒有,您將鎖定您創建的對象。 然后,您可以從地圖中清除該條目。

這顯然不適用於應用程序的許多部署。

有一個叫做 XSync 的工具——一個線程安全的互斥工廠,它提供了通過對象的值(而不是對象)進行同步的能力。 您可以將它用於您需要的所有類型的對象。

https://github.com/antkorwin/xsync

    xSync.execute(contractId, () -> {
           contractService.addAttachment( providerId, contractId, attachment );
    });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM