线程——单例模式
首先我們要了解單例模式,那么什么是單例模式
單例模式:如果一個類在程序中值存在一個實例 通過一定的編程手段來進行限制,防止不小心在代碼中創建了多個實例
單例模式的實現有二種方式一種是餓漢模式另一種是懶漢模式 下面我介紹給大家
餓漢方式
餓漢方式顧名思義就是餓了的人吃飯,只要是能吃的都會直接吃 ,這里對應到代碼就是不管這個對象能不能用到先創建了這個對象在說 下面是代碼的實現
getInstance 得到的類內部的靜態成員
靜態成員是和類相關的(在類對象中),每個類只有一個類對象
此時調用getInstance 得到的實例其實是同一個對象
只要類一被加載就會進行實例化 就會給對象分配內存
懶漢方式
當類加載的時候,不會創建實例,直到第一次使用這個實例了再創建
要比餓漢模式 更加常用 效率高
如果這個對象沒有被使用那么,也就不會被涉及到內存分配,也就節省了不必要開銷
餓漢模式中不管是否用到這個實例,都會分配內存(分配內存操作可能會分配很大的內存,非常消耗時間)
那么在多線程編程的時候單例模型是否安全的,如果不安全應該如何來改進
餓漢模式
實例的創建是在Singleton 類被加載的時候進行的,類被加載的時機只有一次(JVM內部控制的)此時就和多線程無關了
如果多個線程調用getInstance,此時不涉及到多線程同時修改通一個變量,此時也不會有安全問題
懶漢模式
當多個線程同時調用getInstance的時候,有可能會多個線程同時修改,也就存在線程安全問題
本質上還是多個線程修改同一個變量進行修改 并且修改的變量不是原子的
修改操作分為好幾步
1.獲取instance的值
2先判定instance非空
3.非空就new對象
4.把new得到的結果寫回到instance
當instance 為空時 因為是搶占式執行 ,所以會很多的同時獲取到instance 為空時 就會創建很多個對象
存在線程安全問題
那么我們應該怎么樣去解決線程安全問題呢?
沒錯還是加鎖。下面就是懶漢模式的進階版本
當實例被創建之前,多線程調用getInstance ,就會進入第一個if,從而觸發鎖操作,這個鎖操作就能保證線程安全,獲取鎖完畢之后,第二個if 就能保證最終的new值執行一次
如果實例已經被創建之后,多線程調用getInstance,第一個if進不去,也就不會觸發鎖操作(提升了性能,此時也沒有線程安全問題),直接返回instance ,也避免了不必要的鎖開銷
那么這個版本的懶漢模式是否就是線程安全的呢?
不一定,當第一個線程獲取到鎖的時候,其他線程就會快速讀取instance的值,編譯器可能會進行優化,第二次讀到的內容不一定是從內存中重新讀取的,也可能直接使用第一次讀到的結果。
所以它會再去new一個對象,也就不符合單例模式了
那么怎么解決尼 ,可以使用volatile關鍵字 代碼如下
總結
- 上一篇: HALCON示例程序circles.hd
- 下一篇: HALCON示例程序class_2dim