一分鐘理解線程安全
線程安全也叫可重入,是指一段代碼(類、函數)可以在多線程情況下正常工作。
線程安全之所以成為問題是由于:
- 亂序執(zhí)行,為了提高 CPU 的吞吐率,通常會通過亂序技術把“無關”的指令在不同流水線上。
- 層次化存儲,為了綜合訪問存儲的速度、容量、價格,現代計算機通常采用 Cache、主存、外存的層次化存儲。
歸根結底:CPU 太快,存儲太慢,特別是多核、多處理器技術讓 CPU 更快——問題也更加凸出。
讓一個類或者函數線程安全有兩種方法:
- 加鎖,鎖可以讓亂序變的有序;鎖還可以觸發(fā)“回寫”,讓 Cache 和內存保持一致;
- 復制,每個線程一份數據,不共享數據;
實例
Java 中的synchronized關鍵字會為方法增加一個鎖,increase現在是線程安全的,多線程調用時鎖會把并行變成串行。
每個線程都有一個自己的CounterService彼此之間不存在數據共享。
擴展
Spring MVC 中的 Controller 在 BeanFactory 啟動的時候被實例化,對于一個 Controller 而言在整個系統(tǒng)中只有一個實例。所以定義在 Controller 中的成員變量是線程不安全的,比如下面的代碼是錯誤的:
正確的做法應該是:
為方法增加鎖
或者
利用@Scope 注解讓 Spring MVC 每次接到新請求時都重新 new 一個 Controller。
【本文是51CTO專欄作者“邢森”的原創(chuàng)文章,轉載請聯系作者本人獲取授權】