Spring爲什麼是單例的?如何保證線程安全?

單例的好處:

1 減少請求時候創建對象的開銷,提升性能

2 減少jvm垃圾回收

單例的壞處:

1 對於有狀態的變量可能會造成線程安全問題,因爲只有一個實例,如果操作的是有狀態的全局變量,多個線程之間可能會操作同一個變量和對象導致線程不安全問題

 

多例的好處:

1 線程安全,每個請求過來都分配一個新的對象,裏面的所有東西屬性方法都是該線程獨享的

壞處:

1 資源開銷大,創建對象需要消耗性能

2 會產生大量的垃圾對象

 

Spring框架中的bean 或者說組件,默認是單例的。
單例模式確保了某個類只有一個實例,並且自行實例化,向整個系統提供這個實例。
在多線程的情況下,Web容器會向每個請求分配一個線程。這些線程會執行對應的業務邏輯。如果在執行的時候對單例對象進行了修改,則必須考慮到線程同步的問題。

同步機制
ThreadLocal 和 線程同步機制
  線程同步機制中,通過對象的鎖機制保證同一時間只有一個線程訪問變量。這時該變量是多個線程共享的,使用同步機制要求程序慎密地分析什麼時候對變量進行讀寫,什麼時候需要鎖定某個對象,什麼時候釋放對象鎖等繁雜的問題。
  ThreadLocal會爲每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數據的訪問衝突。因爲每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。

對於多線程資源共享的問題,同步機制採用了“以時間換空間”的方式,而ThreadLocal採用了“以空間換時間”的方式。前者僅提供一份變量,讓不同的線程排隊訪問,而後者爲每一個線程都提供了一份變量,因此可以同時訪問而互不影響。 


在spring 中是使用 ThreadLocal 解決線程安全問題
線程安全問題主要是全局變量和靜態變量引起的。
若每個線程中對全局變量、靜態變量讀操作,而無寫操作,一般來說這個全局變量是線程安全的。
若多個線程同時執行寫操作,需要考慮線程同步問題,否則影響線程安全。
spring 使用ThreadLocal 實現高併發下 共享資源的同步。

原理:
  爲每一個使用該變量的線程都提供一個變量值的副本,是每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本衝突。從線程的角度看,就好像每一個線 
程都完全擁有該變量。【每個線程其實是改變的是自己線程的副本,而不是真正要改變的變量,所以效果就是每個線程都有自己的,“這其實就將共享變相爲人人有份!”】 

ThreadLocal 如何實現爲每一個變量維護變量的副本。

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章