在多線程編程中,要確保數據的可見性和正確性,最常見的方式是用鎖來保證同步,但是鎖會帶來額外的開銷,如頻繁的拷貝、線程掛起與恢復等,而AtomicLong則是一種無鎖的同步實現方式,能夠保證線程安全,同時性能也非常不錯。
一、AtomicLong就是原子操作
AtomicLong是Java.util.concurrent.atomic包下的一個類,它對一個長整型值進行原子操作,同時保證在多線程環境下的線程安全。在Java中,原子操作是一種不可分割、不可中斷的操作,只有執行完畢或者不執行。
就是說:要麼成功執行整個操作,要麼就不執行,而不會出現執行了一半就被中斷的情況,這對於高並發場景下的數據修改和讀取是非常有用的。
二、AtomicLong的使用方法
AtomicLong類的常用方法主要有三種:
1. 原子更新基本類型
public final long getAndAdd(long delta) public final long addAndGet(long delta) public final long getAndIncrement() public final long getAndDecrement() public final long getAndSet(long newValue)
這五個方法都是原子性地對一個long類型的變量進行更新。其中,getAndAdd()方法是先獲得當前值,再增加指定的值;addAndGet()方法相反,是先增加指定的值,再獲得新的值;getAndIncrement()方法是先獲得當前值,再自增;getAndDecrement()方法是先獲得當前值,再自減;getAndSet()方法是先獲得當前值,再設置新值。
2. 原子更新數組
public final int getAndAdd(int[] array, int index, int delta) public final int addAndGet(int[] array, int index, int delta) public final int getAndIncrement(int[] array, int index) public final int getAndDecrement(int[] array, int index) public final int getAndSet(int[] array, int index, int newValue)
這五個方法都是原子性地對一個指定下標的整型數組的元素進行更新,其他操作和上面的方法相似。
3. 原子更新:compareAndSet
public final boolean compareAndSet(long expect, long update)
compareAndSet()方法是一個CAS操作,即比較並交換。如果當前值和期望值相等,則更新它為新值,否則不進行任何操作。
三、AtomicLong的例子
1. 使用AtomicLong進行線程安全的計數器操作
public class Counter { private AtomicLong value = new AtomicLong(0L); public long getValue() { return value.get(); } public void increment() { value.incrementAndGet(); } public void add(long delta) { value.addAndGet(delta); } public void decrement() { value.decrementAndGet(); } }
在這個例子中,我們定義了一個計數器類,用於統計某一事件發生的次數。通過使用AtomicLong,我們保證了該計數器是線程安全的。可以看到,我們只需要調用AtomicLong類中提供的方法,就可以完成加減等操作。
2. 使用compareAndSet()方法進行鎖的釋放
public class SpinLock { private AtomicBoolean locked = new AtomicBoolean(false); public void lock() { boolean flag = false; while (!(flag = locked.compareAndSet(false, true))) { // 換成嘗試去獲取鎖的代碼 } } public void unlock() { locked.set(false); } }
在這個例子中,我們定義了一個自旋鎖SpinLock,用於保護臨界區代碼的執行順序。當線程需要進入臨界區時,先調用lock()方法獲取鎖,如果鎖被其他線程佔用,則自旋等待。當線程執行完臨界區代碼後,調用unlock()方法釋放鎖,讓其他線程可以獲取鎖。
四、總結
在多線程編程中,為了保證線程安全,一般需要使用鎖等同步機制。但是,鎖會帶來額外的開銷,影響程序的性能。而AtomicLong則是一種無鎖的線程安全實現方式,它能夠保證線程安全,並且性能非常出色。在實際應用中,可以根據需求使用AtomicLong的各種方法,也可以根據自己的需求實現自己的原子類。無論何種方式,只要遵循了原子操作的規則,就能夠保證線程安全。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/283235.html