什么是原子操作?
所謂原子操作,就是"不可中斷的一個或一系列操作" , 在確認一個操作是原子的情況下,多線程環境里面,我們可以避免僅僅為保護這個操作在外圍加上性能昂貴的鎖,甚至借助于原子操作,我們可以實現互斥鎖。 很多操作系統都為int類型提供了+-賦值的原子操作版本,比如 NT 提供了 InterlockedExchange 等API, Linux/UNIX也提供了atomic_set 等函數。
關于java中的原子性?
原子性可以應用于除long和double之外的所有基本類型之上的“簡單操作”。對于讀取和寫入出long double之外的基本類型變量這樣的操作,可以保證它們會被當作不可分(原子)的操作來操作。 因為JVM的版本和其它的問題,其它的很多操作就不好說了,比如說++操作在C++中是原子操作,但在Java中就不好說了。 另外,Java提供了AtomicInteger等原子類。再就是用原子性來控制并發比較麻煩,也容易出問題。
1)除long和double之外的基本類型的賦值操作
2)所有引用reference的賦值操作
3)java.concurrent.Atomic.* 包中所有類的一切操作
count++不是原子操作,是3個原子操作組合
1.讀取主存中的count值,賦值給一個局部成員變量tmp
2.tmp+1
3.將tmp賦值給count
可能會出現線程1運行到第2步的時候,tmp值為1;這時CPU調度切換到線程2執行完畢,count值為1;切換到線程1,繼續執行第3步,count被賦值為1------------結果就是兩個線程執行完畢,count的值只加了1;
還有一點要注意,如果使用AtomicInteger.set(AtomicInteger.get() + 1),會和上述情況一樣有并發問題,要使用AtomicInteger.getAndIncrement()才可以避免并發問題
package thread.Atomic;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerTest {
public final static AtomicInteger TEST_INTEGER = new AtomicInteger(1);
public static void main(String []args) throws InterruptedException {
final Thread []threads = new Thread[10];
for(int i = 0 ; i < 10 ; i++) {
final int num = i;
threads[i] = new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int now = TEST_INTEGER.incrementAndGet();
System.out.println("我是線程:" + num + ",我得到值了,增加后的值為:" + now);
}
};
threads[i].start();
}
for(Thread t : threads) {
t.join();
}
System.out.println("最終運行結果:" + TEST_INTEGER.get());
}
}
運行結果:
我是線程:1,我得到值了,增加后的值為:3
我是線程:0,我得到值了,增加后的值為:2
我是線程:9,我得到值了,增加后的值為:4
我是線程:4,我得到值了,增加后的值為:9
我是線程:5,我得到值了,增加后的值為:8
我是線程:6,我得到值了,增加后的值為:7
我是線程:8,我得到值了,增加后的值為:5
我是線程:7,我得到值了,增加后的值為:6
我是線程:3,我得到值了,增加后的值為:10
我是線程:2,我得到值了,增加后的值為:11
最終運行結果:11
最終運行結果:11