1. 程式人生 > >執行緒安全性以及Spring中@Controller、@Service的使用

執行緒安全性以及Spring中@Controller、@Service的使用

執行緒安全性定義

多個執行緒同時訪問一個類,不論執行時環境怎樣分配排程方法或者這些執行緒如何交替執行類中的方法,並且呼叫該類方法的多執行緒程式碼不進行同步或協同操作,在這種情況下,這個類表現出的行為都是正確一致的,則稱這個執行緒是安全的。

執行緒安全性體現的三個方面

原子性提供互斥訪問,即同一時刻只能由一個執行緒訪問。
原子性的保障在java中的實現有兩種方式:

  • atomic包
    • 優勢:競爭激烈時能維持常態,比Lock效能好
    • 劣勢:只能同步一個值
  • 加鎖
    • synchronized
    • Lock

可見性:一個執行緒對主記憶體的修改可以及時被其他執行緒觀察到。
導致共享變數不可見的原因:

  • 執行緒交叉執行
  • 重排序結合線程交叉執行
  • 共享變數更新後的值沒有在工作記憶體及時更新

JMM關於synchronized的兩條規定:

  • 執行緒解鎖前,必須把共享變數的最新值重新整理到主記憶體中
  • 執行緒加鎖時,必須從主記憶體中獲取到共享變數最新值

volatile通過加入記憶體屏障禁止重排序優化來實現可見性:

  • 對volatile變數寫操作時,會在寫操作後加入一條store遮蔽指令,將工作記憶體的共享變數值重新整理到主記憶體中
  • 對volatile變數讀操作時,會在讀操作前加入一條load屏障指令,將主記憶體的最新值重新整理到工作記憶體中

volatile關鍵字的應用:

  1. 對狀態進行標識
  2. 保證雙重檢測機制的安全性

有序性,一個執行緒觀察到其他執行緒中指令的執行順序,由於指令重排序的存在,該結果一般是雜亂無章的。
有序性實現的規範,happens-before:

  1. 程式次序規則:一個執行緒內,按照程式碼順序,書寫在前面的操作先發生於書寫在後面的操作
  2. 鎖定規則:一個unlock操作先行發生於lock操作
  3. volatile變數規則:對一個volatile變數的寫先行發生於volatile讀
  4. 傳遞規則:a->b,b->c,a->c
  5. 執行緒啟動規則:Thread物件的start()方法先行發生於此執行緒的每一個動作
  6. 執行緒中斷規則:對執行緒的interrupt()方法的呼叫先行發生於被中斷執行緒的程式碼檢測到中斷髮生
  7. 執行緒終結規則:執行緒中所有的操作都先行發生於執行緒的終止檢測,我們可以通過Thread.join()方法結束Thread.isAlive()的返回值檢測到執行緒已經終止執行
  8. 物件終結規則:一個物件的初始化先行發生於它的finalize()方法的開始

不安全的物件的識別以及怎樣預防物件的非執行緒安全

一個不安全的物件通常作為共享變數而存在,多個執行緒訪問這個物件進行修改導致多次執行結果不一致。

  • 執行緒封閉
    • 堆疊封閉:利用變數的區域性性保證區域性執行緒安全
    • 執行緒封閉:ThreadLocal繫結物件在特定執行緒上
  • 釋出物件:使一個物件能夠被當前範圍之外的程式碼所使用
    • 物件逸出
      • 一種錯誤的釋出方式,物件還沒有完成構造時,就使它被其他執行緒所見
      • 一種常見的方式是,構造器內部呼叫內部類,內部類獲取外部類this引用造成執行緒不安全
    • 安全釋出物件
      • 靜態初始化函式中初始化一個物件引用
      • 將物件的引用儲存到volatile型別域或者AtomicReference物件中
      • 將物件的引用儲存到某個正確構造物件的final型別域
        • 不可變物件
          • 物件建立後其狀態不可變
          • 物件所有域都是final型別
          • 物件是正確建立的(物件建立期間,this引用沒有逸出)
          • 一個類的private方法會被隱式的修飾為final方法
          • final修飾的變數
            • 基本型別final修飾後不可更改
            • 引用型別的final修飾變數後引用不可以指向新的物件,但是可以改變原有物件值
              • 只用final修飾類屬性則不是執行緒安全的
      • 將物件的引用儲存到一個由鎖保護的域中
  • Atomic包
    • AtomicInteger
    • AtomicLong和LongAddr
    • AtomicReference和AtomicReferenceFieldUpdater
    • AtomicStampReference
      • 解決CAS的ABA問題

Spring框架中@Controller、@Service

Spring框架中Controller和Service預設使用單例,通過單例來重用同一個Controller和Service好處顯而易見,但是仔細想想好像會導致執行緒不安全:

  • 如果service類定義了其他成員變數,並且不加額外的保護措施,當controller呼叫service的方法並有修改service成員變數的操作時,此時多執行緒併發就暴露出問題了
  • 我們平時針對Service程式設計,都只是在Controller內部呼叫Service的方法,並沒有對Service例項屬性(如果有的話) 進行額外的更新操作,所以保證的執行緒的安全性
  • 當我們需要儲存其他屬性時,可以通過加鎖、執行緒封閉等操作保證對屬性的操作是執行緒安全的

相關推薦

執行安全性以及Spring@Controller@Service的使用

執行緒安全性定義 多個執行緒同時訪問一個類,不論執行時環境怎樣分配排程方法或者這些執行緒如何交替執行類中的方法,並且呼叫該類方法的多執行緒程式碼不進行同步或協同操作,在這種情況下,這個類表現出的行為都是正確一致的,則稱這個執行緒是安全的。 執行緒安全性體

Java執行狀態以及 sheep()wait()yield() 的區別

前言 最近看到很多人都在討論多執行緒的問題,於是寫出了這篇部落格,希望可以幫到正在學習和使用這塊的朋友們,首先我們先看看兩個圖(兩個圖都來自其他碼農的分享)。   這兩個圖是一樣的邏輯,這裡一起羅列出來,下面讓我們用語句來簡單描述下兩個圖: sleep 讓執行緒從 【run

SpringControllerServiceDao進行Junit單元測試總結

Spring對Controller、Service、Dao進行Junit單元測試總結 [email protected]事務控制,避免資料庫出現髒資料(若要提交到資料庫,先注掉) 2.hibernate配置檔案 <property name="defaultAutoComm

Spring 執行安全性

Spring與執行緒安全   Spring作為一個IOC/DI容器,幫助我們管理了許許多多的“bean”。但其實,Spring並沒有保證這些物件的執行緒安全,需要由開發者自己編寫解決執行緒安全問題的程式碼。   Spring對每個bean提供了一個s

Spring執行安全性

一:Spring與執行緒安全 Spring作為一個IOC/DI容器,幫助我們管理了許許多多的“bean”。但其實,Spring並沒有保證這些物件的執行緒安全,需要由開發者自己編寫解決執行緒安全問題的程式碼。 Spring對每個bean提供了一個scope屬性來表示該bean的作用域。它是be

Spring MVC Controller執行安全性問題

Spring MVC預設是單例模式,Controller、Service、Dao都是單例所以在使用不當存在一定的安全隱患。Controller單例模式的好處在與: 1. 提高效能,不用每次建立Con

第5章:作為Web應用:屬性和監聽者/5.4 Servlet屬性的執行安全性請求屬性與請求分派

上下文屬性 它不是執行緒安全的,因為它屬於應用所有,全部servlet都都可以修改它,所以在呼叫setAttribute,removeAttribute時要加鎖操作 操作方法如:,鎖要針對getServletContext物件   請求屬性

jni執行, 同步以及生產者消費者模式

編譯環境centos6.×64 執行緒建立以及結束 #include <pthread.h> pthread_create (thread, attr, start_routine, arg) 連線和分離執行緒 pthrea

Spring併發訪問的執行安全性問題總結

好像是在去年畢業面試的時候,面試官問了我這個問題,如何保證Spring併發訪問的執行緒安全問題,當時的我也只是對這些有所瞭解,僅僅知道spring中的controller、serivce、dao預設為單例,只要不在這些單例中使用成員變數就可以了,然後工作至今,我還是對其中原理

資料庫事務的四大特性隔離級別以及Spring如何利用AOP進行事務管理

首先,什麼是事務? 事務就是業務上的一個邏輯單元,它能夠保證其中對資料所有的操作,要麼成功,要麼失敗。 其次,事務的特性有哪些? 1.原子性。 例如,轉賬,A賬戶減少,B賬戶增加。雖然是兩條 DML語句,但是被當做是一個整體,一次事務。兩條語句只能同時成功或者同時失敗。 2

Spring併發訪問的執行安全性問題(高度總結)

spring中的併發訪問題: 我們知道在一般情況下,只有無狀態的Bean才可以在多執行緒環境下共享,在Spring中,絕大部分Bean都可以宣告為singleton作用域。 那麼對於有狀態的bean呢?Spring對一些(如RequestContextHolder、Tra

Spring 是如何解決併發訪問的執行安全性問題的

        springmvc的controller是singleton的(非執行緒安全的),這也許就是他和struts2的區別吧!和Struts一樣,Spring的Controller預設是Singleton的,這意味著每個request過來,系統都會用原有的inst

javaWriter的執行安全性

以前負責一個專案,我負責從一個超大的文字檔案中讀取資訊存入資料庫再進一步分析。而文字檔案內容是每行一個json串。我在解析的過程中發現,有很小的概率json串的結構會破壞,比如前一個json串只寫了半行,後面就被另一個json串覆蓋掉了。 與產生日誌的部門溝通,他們說是多執行緒使用log4j寫入,可能偶爾會

[netty]--Reactor執行模型以及在netty的應用

說道netty的執行緒模型,我們第一反應就是經典的Reactor執行緒模型,下面我們就來一起探討一下三種經典的Reactor執行緒模型: 這裡我們需要理解的一點是Reactor執行緒模型是基於同步非阻塞IO實現的。對於非同步非阻塞IO的實現是Pr

Spring併發訪問的執行安全性問題

springmvc的controller是singleton的(非執行緒安全的),這也許就是他和struts2的區別吧和Struts一樣,Spring的Controller預設是Singleton的,這意味著每個request過來,系統都會用原有的instance去處理,這

java執行以及newCachedThreadPool使用過程的問題

      為什麼要用執行緒池?原因很簡單,效能好,而且不用自己費心費力的管理執行緒       1、執行緒池基本說明及定義       從JDK 1.5開始,添加了Executors工具類,這個類定義了Executor、ExecutorService、ScheduledE

Java如何保證執行安全性

一、執行緒安全在三個方面體現1.原子性:提供互斥訪問,同一時刻只能有一個執行緒對資料進行操作,(atomic,synchronized);2.可見性:一個執行緒對主記憶體的修改可以及時地被其他執行緒看到,(synchronized,volatile);3.有序性:一個執行緒觀

linux 程序執行(or子程序)資源佔用檢視以及顯示資料的意義

檢視程序: ps -ef | more  (-e:所有程序,-f:全格式) ++++++++++++++++++++++++++++++++++++ + UID :使用者ID                     + + PID :程序ID                

淺談springAOP以及springAOP的註解方式

早就 好的 面向 XML ram ati alt 返回 增強   AOP(Aspect Oriented Programming):AOP的專業術語是"面向切面編程" 什麽是面向切面編程,我的理解就是:在不修改源代碼的情況下增強功能.好了,下面在講述aop註解方式的情況下順

spring Boot】Spring@Controller和@RestController之間的區別

處理 public 不同 esp 舉例 rest control tro adding spring Boot入手的第一天,看到例子中的@RestController ............. 相同點:都是用來表示Spring某個類的是否可以接收HTTP請求 不同點:@C