🔁 解決 Java 中的 ABA 問題 — 使用 AtomicStampedReference
❓ 什麼是 ABA 問題?ABA 問題發生在使用 CAS(Compare-And-Swap)時: 執行緒 A 讀到某個變數值為 A 執行緒 B 將該變數從 A ➝ B ➝ A 執行緒 A 再次使用 CAS,認為值沒變,繼續執行,但其實值已變動過! 這會導致程式誤以為狀態未變,但實際上已經被其他執行緒修改過。 🧰 解法:使用 AtomicStampedReferenceJava 提供 AtomicStampedReference<T>,這是一種「附加版本號(stamp)」的原子參考,可以避免 ABA 問題。 它在每次變更時,都會同步更新一個 stamp 值,用來追蹤版本。 🧪 範例程式碼123456789101112131415161718192021222324252627import java.util.concurrent.atomic.AtomicStampedReference;public class AbaProblemSolution { public static void main(String[] args)...
☕ Java 原子性變數與 CAS 筆記
📌 一、什麼是「原子性變數」與 CAS?在多執行緒環境下,多個執行緒若同時修改同一個變數,容易發生資料競爭。 Java 提供 java.util.concurrent.atomic 套件,裡面有許多「原子操作」的變數類型,例如: AtomicInteger AtomicLong AtomicReference 這些類別提供 非阻塞(non-blocking) 的操作方式,底層就是使用 CAS(Compare-And-Swap,比較並交換) 實作的。 ⚙️ 二、CAS 的核心邏輯CAS 是一種樂觀鎖策略,基本流程如下: 讀取目前值 比對是否與預期值一致 若一致,就更新為新值 若不一致,就放棄(重試或結束) ✅ 優點:不用 synchronized 就能寫出安全的多執行緒操作 ❌ 缺點:高併發時可能需要一直 retry,自旋過多會浪費 CPU 💡 三、實際範例:用 CAS 實作「無鎖計數器」1234567891011121314151617181920212223242526272829303132333435363738import...
從 Identity 欄位極限值看資料庫運作:實戰查詢範例分享
在這篇文章中,我想跟各位分享一個相當有趣又實用的 SQL 查詢範例。這支查詢主要用來檢查資料庫中各個資料表的 Identity 欄位(通常作為主鍵使用)的目前值(last_value),並根據該欄位的資料型態來推算其可能達到的最大極限值。 查詢範例以下就是完整的 SQL 查詢程式碼: 12345678910111213141516SELECT OBJECT_NAME(ic.object_id) AS TableName, ic.name AS IdentityColumn, ic.last_value AS CurrentValue, CASE WHEN ty.name = 'tinyint' THEN 255 WHEN ty.name = 'smallint' THEN 32767 WHEN ty.name = 'int' THEN 2147483647 ...
資料表重新建立及資料遷移 SOP
💡 Purpose: 此 SOP 說明如何從原始資料表進行備份、建立新表、資料遷移以及重新命名,目的是因應原資料表主鍵未設定自動遞增,需先備份資料,再依新的 DDL 語法建立自動遞增主鍵的表結構,最後將資料還原。請務必在每個步驟執行前確認相關操作已備份完成,以避免資料遺失。 前置檢查步驟 0:檢查表結構與資料筆數 取得資料表結構,確認是否已有自動遞增主鍵。 1exec sp_columns WCSTXXX; 檢查主鍵(例如:WCSID)是否有重複筆數: 1234select WCSID, COUNT(*)from WCSTXXXgroup by WCSIDhaving COUNT(*) > 1; 檢查資料表的總筆數: 1select COUNT(*) from WCSTXXX; 注意: 請將檢查結果記錄下來,作為後續參考依據。 備份原始資料步驟 1:備份現有資料表 將現有資料完整備份至另一張暫存表中,避免後續操作造成資料遺失: 1select * into backup_WCSTXXX from WCSTXXX; 建立新資料表步驟...
統計資料庫所有表的筆數與完整性校驗(CheckSum)
今天來分享幾個在 SQL Server 2008 裡,如何比對資料表內容的小技巧,讓你可以快速檢查資料是否有異動。以下會介紹三種方法,分別適用於不同的情境,親自實測過,效果滿不錯的喔! 方法 1:用 CHECKSUM_AGG 來計算表格變更這個方法是利用 CHECKSUM_AGG(BINARY_CHECKSUM(*)) 來算出整個資料表的檢查碼。它的優點就是運算速度快,不會遇到像 XML 轉換那種限制,缺點則是有可能會發生碰撞(就是不同資料卻得到一樣的檢查碼),而且對於 BLOB 或浮點數欄位就不太適合。 123456789SELECT s.name AS SchemaName, t.name AS TableName, CHECKSUM_AGG(BINARY_CHECKSUM(*)) AS TableChecksumFROM sys.tables t INNER JOIN sys.schemas s ON t.schema_id = s.schema_idWHERE s.name = 'dbo'GROUP BY...
多執行緒的相關術語
序列(串行):任務依照先後順序逐一執行,必須等前一個任務完成後,下一個任務才會開始執行。 並發(交替執行):多個任務在同一單位時間內交替執行,從宏觀上看似乎同時進行,但在任何特定時刻,實際上僅有一個任務在執行。這種模式通常發生在單核心或單執行緒環境下。 平行(真正同時執行):多個任務能夠在相同時刻真正地同時運行,這通常依賴於多核心處理器或多處理器系統,使得各任務可分派到不同的核心上同步執行。 1. 序列(串行)所有任務按順序執行,一個完成後才開始下一個。 程式碼12345678910111213141516171819202122public class SequentialExample { public static void main(String[] args) { long startTime = System.currentTimeMillis(); task("Task 1"); task("Task 2"); ...
查看MSSQL資料庫的佔用空間
在 MSSQL 中,可以通過系統檢視或內建存儲過程來查看資料庫的大小,包括資料和索引的占用。以下是常用的方法: 方法 1:使用 sp_spaceusedsp_spaceused 是一個內建的存儲過程,用於查看資料庫的空間使用情況。 查看整個資料庫的大小 切換到目標資料庫: 12USE [YourDatabaseName];GO 執行以下命令:返回的關鍵結果: 1EXEC sp_spaceused; database_size:資料庫的總大小(資料和索引)。 unallocated space:未分配的空間。 查看特定表的大小 執行以下命令:返回的關鍵結果: 1EXEC sp_spaceused N'[YourTableName]'; reserved:表的總預留空間(資料、索引和未使用空間)。 data:表中資料的大小。 index_size:表的索引大小。 unused:未使用的空間。 方法 2:使用 sys.master_files 和...
分散式系統的CAP定理(CAP theorem)
在設計分散式系統(Distributed System)前,必須要了解CAP定理(CAP theorem),又稱布魯爾定理(Brewer’s theorem)。 CAP定理的三個字母C,A,P分別代表以下: Consistency:一致性 Availability:可用性 Partition-tolerance:分區容錯 Consistency 一致性指分散式系統中的每個節點(nodes)所查到的都是一致且最新的資料。 Availability 可用性在任何時候,每次向系統發出請求都能在合理的時間內獲得回應,但並不保證回應的資料為最新。 Partition-tolerance 分區容錯當網路或節點故障造成系統的不同網路分區間(Partitions)的傳輸資料丟失時,系統仍可以正常運作。 滿足以上三種特性是一個完美的分散式系統欲達成的目標。 不過CAP定理指出,一個分散式系統最多只能滿足以上三個特性中的兩個,而無法同時滿足三個。 You can have at most two of these properties for any shared-data...
Hibernate → @DiscriminatorColumn說明
@DiscriminatorColumn 註解用於在 JPA 繼承結構中,為單表策略 (InheritanceType.SINGLE_TABLE) 的繼承層次結構指定區分列。這樣,JPA 可以使用這個列來識別每一行對應的具體實體類型。 讓我們詳細解釋一下: 註解部分1@DiscriminatorColumn(name="accountType", discriminatorType = DiscriminatorType.STRING) @DiscriminatorColumn:這個註解指定了用來區分不同實體類型的列。 name="accountType":這指定了區分列的名稱為 accountType。這個列將會被添加到生成的單表中,用來存儲每一行對應的實體類型。 discriminatorType = DiscriminatorType.STRING:這指定了區分列的類型為 STRING。區分列可以是 STRING、CHAR 或 INTEGER。 作用當使用 InheritanceType.SINGLE_TABLE...
HashMap → computeIfAbsent()
12345678910// 當key不存在,就執行第二個參數的函數,並回傳執行後的值,然後也會put// 如果函數返回 null,則不會put// 如果函數本身拋出(未經檢查的)異常,則重新拋出異常,則不會putpublic static void main(String[] args) { Map<String, Integer> stringLength = new HashMap<>(); stringLength.put("John", 2); int i = stringLength.computeIfAbsent("John", String::length); System.out.println("i = " + i); System.out.println("stringLength = " +...