分散式環境下,怎麼保證執行緒安全
避免併發
在分散式環境中,如果存在併發問題,那麼很難通過技術去解決,或者解決的代價很大,所以我們首先要想想是不是可以通過某些策略和業務設計來避免併發。比如通過合理的時間排程,避開共享資源的存取衝突。另外,在並行任務設計上可以通過適當的策略,保證任務與任務之間不存在共享資源,比如在以前博文中提到的例子,我們需要用多執行緒或分散式叢集來計算一堆客戶的相關統計值,由於客戶的統計值是共享資料,因此會有併發潛在可能。但從業務上我們可以分析出客戶與客戶之間 資料是不共享的,因此可以設計一個規則來保證一個客戶的計算工作和資料訪問只會被一個執行緒或一臺工作機完成,而不是把一個客戶的計算工作分配給多個執行緒去 完成。這種規則很容易設計,例如可以採用hash演算法。
時間戳
分散式環境中併發是沒法保證時序的,無論是通過遠端介面的同步呼叫或非同步訊息,因此很容易造成某些對時序性有要求的業務在高併發時產生錯誤。比如系統A需要把某個值的變更同步到系統B,由於通知的時序問題會導致一個過期的值覆蓋了有效值。對於這個問題,常用的辦法就是採用時間戳的方式,每次系統A傳送變更給系統B的時候需要帶上一個能標示時序的時間戳,系統B接到通知後會拿時間戳與存在的時間戳比較,只有當通知的時間戳大於存在的時間戳,才做更新。這種方式比較簡單,但關鍵在於呼叫方一般要保證時間戳的時序有效性。
序列化
有的時候可以通過序列化可能產生併發問題操作,犧牲效能和擴充套件性,來滿足對資料一致性的要求。比如分散式訊息系統就沒法保證訊息的有序性,但可以通過變分散式訊息系統為單一系統就可以保證訊息的有序性了。另外,當接收方沒法處理呼叫有序性,可以通過一個佇列先把呼叫資訊快取起來,然後再序列地處理這些呼叫。
資料庫
分散式環境中的共享資源不能通過Java裡同步方法或加鎖來保證執行緒安全,但資料庫是分散式各伺服器的共享點,可以通過資料庫的高可靠一致性機制來滿足需求。比如,可以通過唯一性索引來解決併發過程中重複資料的生產或重複任務的執行;另外有些更新計算操作也儘量通過sql來完成,因為在程式段計算好後再去更新就有可能發生髒複寫問題,但通過一條sql來完成計算和更新就可以通過資料庫的鎖機制來保證update操作的一致性。
行鎖
有的事務比較複雜,無法通過一條sql解決問題,並且有存在併發問題,這時就需要通過行鎖來解決,一般行鎖可以通過以下方式來實現:
對於Oracle資料庫,可以採用select ... for update方式。這種方式會有潛在的危險,就是如果沒有commit就會造成這行資料被鎖住,其他有涉及到這行資料的任務都會被掛起,應該謹慎使用
在表裡新增一個標示鎖的欄位,每次操作前,先通過update這個鎖欄位來完成類似競爭鎖的操作,操作完成後在update鎖欄位復位,標示已歸還鎖。這種方式比較安全,不好的地方在於這些update鎖欄位的操作就是額外的效能消耗
統一觸發途徑
當一個數據可能會被多個觸發點或多個業務涉及到,就有併發問題產生的隱患,因此可以通過前期架構和業務設計,儘量統一觸發途徑,觸發途徑少了一是減少併發的可能,也有利於對於併發問題的分析和判斷。
相關推薦
消費RabbitMQ時的注意事項,如何禁止大量的訊息湧到Consumer,保證執行緒安全
按照官網提供的訂閱型寫法( Retrieving Messages By Subscription ("push API")) 我發現,RabbitMQ伺服器會在短時間內傳送大量的訊息給Consumer,然後,如果你沒有來得及Ack的話,那麼服務端會積壓大量的UnAcked訊息,而Cons
分散式環境下,怎麼保證執行緒安全
避免併發 在分散式環境中,如果存在併發問題,那麼很難通過技術去解決,或者解決的代價很大,所以我們首先要想想是不是可以通過某些策略和業務設計來避免併發。比如通過合理的時間排程,避開共享資源的存取衝突。另外,在並行任務設計上可以通過適當的策略,保證任務與任務之間不存在共享資
volatile不能保證原子性,也就不能保證執行緒安全
volatile只能保證變數的可見性,無法保證對變數的操作的原子性。 還是以最常用的i++來說吧,包含3個步驟 1,從記憶體讀取i當前的值 2,加1 3,把修改後的值重新整理到記憶體 對於普通變數來說多執行緒下1,2之間被中斷,其
C# Winform專案中多執行緒環境下, 如何跨執行緒對Window窗體控制元件進行安全訪問?
請嘗試執行這段程式碼, 結果你會發現微軟開發工具會提示, Tb_Text.Text = int_Index.ToString(); 涉及"對Windows窗體控制元件進行執行緒安全呼叫", 並給瞭如下的解決方案:https://msdn.microsoft.com/zh-cn/library/ms171728
[unix]兩個互斥量保護共享變數自增,保證執行緒執行安全例項
#include "apue.h" #include <pthread.h> #define NHASH 29 #define HASH(id) (((unsigned long)id)%NHASH) struct foo *fh[NHASH];
AtomicInteger如何保證執行緒安全以及樂觀鎖/悲觀鎖的概念
最近面試被問到一個問題,AtomicInteger如何保證執行緒安全?我查閱了資料 發現還可以引申到 樂觀鎖/悲觀鎖的概念,覺得值得一記。 眾所周知,JDK提供了AtomicInteger保證對數字的操作是執行緒安全的,執行緒安全我首先想到了synchronized和Lock,但是這
iOS中保證執行緒安全的幾種方式與效能對比
一、前言 前段時間看了幾個開源專案,發現他們保持執行緒同步的方式各不相同,有@synchronized、NSLock、dispatch_semaphore、NSCondition、pthread_mutex、OSSpinLock。後來網上查了一下,發現他們的實現機制各不相同,效能也各不一
單例模式(上)---如何優雅地保證執行緒安全問題
上次帥地問的問題,讓小秋學習了不少。這幾天小秋剛好學習了一些設計模式的知識,這不,又跑去找帥地探討一些問題了。 粗糙的同步 小秋:地哥,上次你問的問題,讓我收穫頗多,這些天我大致研究了下設計模式,帥地有什麼指教的嗎? 帥地:小子,行啊。那我再考考你得了。 此刻小秋聚精會神著等帥地又會丟擲哪些問題….. 帥地
2.hashMap如何保證執行緒安全
一:hashMap執行緒不安全表現 (1)在兩個執行緒同時嘗試擴容HashMap時,可能將一個連結串列形成環形的連結串列,所有的next都不為空,進入死迴圈; (2)在兩個執行緒同時進行put時可能造成一個執行緒資料的丟失; 二:如何執行緒安全的使用hashMap (
靜態內部類實現的單例模式是如何保證執行緒安全的
靜態內部類實現的單例模式如下: public class Singleton { private Singleton(){ } public static Singleton getInstance(){
i++和++i的區別,及其執行緒安全問題
i++和++i都是i=i+1的意思,但是過程有些許區別:i++:先賦值再自加。(例如:i=1;a=1+i++;結果為a=1+1=2,語句執行完後i再進行自加為2)++i:先自加再賦值。(例如:i=1;a=1+++i;結果為a=1+(1+1)=3,i先自加為2再進行運算)但是在
高併發下最全執行緒安全的單例模式幾種實現
為了節約系統資源,有時需要確保系統中某個類只有唯一一個例項,當這個唯一例項建立成功之後,我們無法再建立一個同類型的其他物件,所有的操作都只能基於這個唯一例項。 但是餓漢式單例類不能實現延遲載入,不管將來用不用始終佔據記憶體;懶漢式單例類執行緒安全控制煩瑣,而且效能受影響。可
ThreadLocal-單例模式下高併發執行緒安全
MirrorThread: public class MirrorThread extends Thread{ private Mirror mirror; private String threadName; public MirrorThread(Mirror mirror, Stri
寫一下單例模式,考慮執行緒安全與執行緒不安全的情況
凡是提到設計模式,面試官很喜歡問最簡單的單例模式。 方法一 單例模式最簡單的寫法如下 public class SingletonPatternA { private static SingletonPatternA instance =
多執行緒 ThreadGroup activeCount沒有作用的情況下,多執行緒也可以自己寫,ThreadGroup不一定好使
這裡只採用了Queue佇列的方式來,自己模擬ThreadGroup的功能實現private static final ThreadGroup tg = new ThreadGroup("tg");int num = tg.activeCount()有時候num取得會有誤,原
單例設計模式(餓漢式,懶漢式(1,有執行緒安全問題,2,安全高效))
package cn.itcast.mobilesafexian2.test; public class Student { /* (1)單例模式(只需建立一個物件) (外界訪問直接Student.getStudent 即可獲得物件 ) (餓漢式:在載入的時候建立物件{
什麼是執行緒安全?如何保證執行緒安全?
執行緒安全:就是多執行緒訪問同一程式碼,不會產生不確定結果。(比如死鎖) 如何保證呢:1使用執行緒安全的類 2使用synchronized同步程式碼塊,或者用Lock鎖 3多執行緒併發情況下,執行
淺談Java併發程式設計系列(一)—— 如何保證執行緒安全
執行緒安全類 保證類執行緒安全的措施: 不共享執行緒間的變數; 設定屬性變數為不可變變數; 每個共享的可變變數都使用一個確定的鎖保護; 保證執行緒安全的思路: 通過架構設計 通過
Java多執行緒有哪幾種實現方式? Java中的類如何保證執行緒安全? 請說明ThreadLocal的用法和適用場景(面試題)
Java多執行緒有哪幾種實現方式? Java中的類如何保證執行緒安全? 請說明ThreadLocal的用法和適用場景 Java多執行緒有三種實現方式: (1)繼承Thread類,重寫run函式 (2)實現Runnable介面,重寫run函式 開啟執行緒:Thread t
多執行緒中如何去保證執行緒安全
一、前言 前段時間看了幾個開源專案,發現他們保持執行緒同步的方式各不相同,有@synchronized、NSLock、dispatch_semaphore、NSCondition、pthread_mutex、OSSpinLock。後來網上查了一下,發現他們的實現機制各不相同,效能也各不一樣。