在多線程,共享實體主要會在以下情況下導致問題:並發性被合並。共享實體,例如,可變的對象或變量可能會被更改,這可能會導致程序的不一致或數據庫。因此,在並發訪問時處理共享實體變得至關重要。一個原子變量可以是這種情況下的替代方案之一。
Java提供原子類如AtomicInteger,AtomicLong,AtomicBoolean和AtomicReference。這些類的對象代表原子變量分別為 int、long、boolean 和對象引用。這些類包含以下方法。
- 設置(整數值):設置為給定值
- get():獲取當前值
- 惰性設置(int值):最終設置為給定值
- CompareAndSet(int期望,int更新):如果當前值 == 預期值,則自動將該值設置為給定的更新值
- addAndGet(int delta):以原子方式將給定值添加到當前值
- decrementAndGet():以原子方式將當前值減一
例子:
// Atomic Variable AtomicInteger var;
需要原子變量
考慮下麵的例子:
Java
class Counter extends Thread {
// Counter Variable
int count = 0;
// method which would be called upon
// the start of execution of a thread
public void run()
{
int max = 1_000_00_000;
// incrementing counter
// total of max times
for (int i = 0; i < max; i++) {
count++;
}
}
}
public class UnSafeCounter {
public static void main(String[] args)
throws InterruptedException
{
// Instance of Counter Class
Counter c = new Counter();
// Defining Two different threads
Thread first = new Thread(c, "First");
Thread second = new Thread(c, "Second");
// Threads start executing
first.start();
second.start();
// main thread will wait for
// both threads to get completed
first.join();
second.join();
// Printing final value of count variable
System.out.println(c.count);
}
}
輸出:
137754082
在單線程環境中,上述類隻會給出預期的結果。但當涉及到多線程環境時,可能會導致結果不一致。發生這種情況是因為更新 “var” 是通過三個步驟完成的:讀取、更新和寫入。如果兩個或更多線程嘗試同時更新該值,則它可能無法正確更新。
這個問題可以使用 Lock and Synchronization 解決,但效率不高。
1.使用鎖類比或同步:同步或鎖定可以解決我們的問題,但它會損害時間效率或性能。首先,它要求資源和線程調度程序來控製鎖。其次,當多個線程嘗試獲取鎖時,隻有一個線程獲勝,其餘線程被掛起或阻塞。掛起或阻塞線程會對性能產生巨大影響。
Java
import java.io.*;
import java.util.concurrent.locks.*;
class Counter extends Thread {
// Counter Variable
int count = 0;
// method which would be called upon
// the start of execution of a thread
public synchronized void run()
{
int max = 1_000_00_000;
// incrementing counter total of max times
for (int i = 0; i < max; i++) {
count++;
}
}
}
public class SynchronizedCounter {
public static void main(String[] args)
throws InterruptedException
{
// Instance of Counter Class
Counter c = new Counter();
// Defining Two different threads
Thread first = new Thread(c, "First");
Thread second = new Thread(c, "Second");
// Threads start executing
first.start();
second.start();
// main thread will wait for both
// threads to complete execution
first.join();
second.join();
// Printing final value of count variable
System.out.println(c.count);
}
}
輸出:
200000000
2.使用原子變量:
Java
import java.util.concurrent.atomic.AtomicInteger;
class Counter extends Thread {
// Atomic counter Variable
AtomicInteger count;
// Constructor of class
Counter()
{
count = new AtomicInteger();
}
// method which would be called upon
// the start of execution of a thread
public void run()
{
int max = 1_000_00_000;
// incrementing counter total of max times
for (int i = 0; i < max; i++) {
count.addAndGet(1);
}
}
}
public class AtomicCounter {
public static void main(String[] args)
throws InterruptedException
{
// Instance of Counter Class
Counter c = new Counter();
// Defining Two different threads
Thread first = new Thread(c, "First");
Thread second = new Thread(c, "Second");
// Threads start executing
first.start();
second.start();
// main thread will wait for both
// threads to complete execution
first.join();
second.join();
// Printing final value of count variable
System.out.println(c.count);
}
}
輸出:
200000000
相關用法
- Java AtomicReference lazySet()用法及代碼示例
- Java AtomicReference getPlain()用法及代碼示例
- Java AtomicReference getOpaque()用法及代碼示例
- Java AtomicReference getAndSet()用法及代碼示例
- Java AtomicReference getAndAccumulate()用法及代碼示例
- Java AtomicReference getAcquire()用法及代碼示例
- Java AtomicReference compareAndSet()用法及代碼示例
- Java AtomicReference compareAndExchangeRelease()用法及代碼示例
- Java AtomicReference get()用法及代碼示例
- Java AtomicBoolean get()用法及代碼示例
- Java AtomicBoolean compareAndSet()用法及代碼示例
- Java AtomicBoolean getAndSet()用法及代碼示例
- Java AtomicBoolean lazySet()用法及代碼示例
- Java AtomicBoolean set()用法及代碼示例
- Java AtomicBoolean toString()用法及代碼示例
- Java AtomicInteger accumulateAndGet()用法及代碼示例
- Java AtomicInteger addAndGet()用法及代碼示例
- Java AtomicInteger compareAndSet()用法及代碼示例
- Java AtomicInteger decrementAndGet()用法及代碼示例
- Java AtomicInteger doubleValue()用法及代碼示例
- Java AtomicInteger floatValue()用法及代碼示例
- Java AtomicInteger get()用法及代碼示例
- Java AtomicInteger getAndAccumulate()用法及代碼示例
- Java AtomicInteger getAndAdd()用法及代碼示例
- Java AtomicInteger getAndDecrement()用法及代碼示例
注:本文由純淨天空篩選整理自NiravTalaviya大神的英文原創作品 Atomic Variables in Java with Examples。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。