原子性(排他性):不論是多核還是單核,具有原子性的量,同一時刻只能有一個線程來對它進行操作!
可見性:多個線程對同一份數據操作,thread1改變了某個變量的值,要保證thread2能看見這個值被改變了。
static
靜態的,在程序執行的時候,就已經加載或執行。
修飾方法、變量、代碼塊。
靜態方法不能引用非靜態的變量和方法。因為非靜態的方法和變量只有在具體的實例存在才會相應的加載。
同時被static修飾的成員變量和成員方法是獨立于該類的,它不依賴于某個特定的實例變量,也就是說它被該類的所有實例共享。所有實例的引用都指向同一個地方,任何一個實例對其的修改都會導致其他實例的變化。每個實例指向的都是同一個堆地址區域,修改的都是同一塊內存。
保證了變量在該類所有的實例中的唯一性。
static為什么不能保證線程安全???
每個線程運行時都有一個線程棧,線程棧保存了線程運行時候變量值信息。當線程訪問某一個對象時候值的時候,首先通過對象的引用找到對應在堆內存的變量的值,然后把堆內存變量的具體值load到線程本地內存中,建立一個變量副本,之后線程就不再和對象在堆內存變量值有任何關系,而是直接修改副本變量的值,在修改完之后的某一個時刻(線程退出之前),自動把線程變量副本的值回寫到對象在堆中變量。這樣在堆中的對象的值就產生變化了。

摘自:http://www.cnblogs.com/shangxiaofei/p/5564340.html
這樣就會導致多線程帶來的問題,多個線程都從主內存私有拷貝變量到自己的工作區,a線程改變了var1的值,進行+1操作,還沒寫回到主內存。b線程這時看到自己的工作區中的var1值沒變。這就是多線程帶來的問題。
那么如何保證變量在多線程中的安全?(有人說可以聲明為final類型,但是這樣就是常量了。)
volatile
volatile,聲明這個字段易變(可能被多個線程使用),Java內存模型負責各個線程的工作區與主存區的該字段的值保持同步,即一致性。
volatile禁止編譯器對成員變量進行優化,被volatile聲明的變量,多個線程在操作的時候,每改變其值的時候,jvm都強行要求其立刻寫回主內存。每次使用其值的時候,都要求其從主內存重新拷貝。這樣就保證了操作的可見性,但是并不能保證操作的原子性,多個線程仍然可以對其進行同時操作。在某種情況下,volatile還是不能保證線程的安全。
那么如何保證多線程的安全?
synchronize
建議看此篇
http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html
區別
static只是聲明變量在主存上的唯一性,不能保證工作區與主存區變量值的一致性;除非變量的值是不可變的,即再加上final的修飾符,否則static聲明的變量,不是線程安全的。
volatile同步機制不同于synchronized,前者是內存同步,后者不僅包含內存同步(一致性),且保證線程互斥(互斥性)。
synchronized:其實就像加了鎖一樣,只能等待這個線程操作完變量,并且把變量值同步到堆(主內存后),釋放鎖;然后其他線程才可以讀寫。
ReentrantLock:ReentrantLock多了鎖投票,定時鎖等候,中斷鎖等候;synchronized鎖不能被打斷;競爭激烈的時候,使用此鎖,效率更高些。