當前位置:首頁 » 硬碟大全 » 並發代碼緩存鎖
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

並發代碼緩存鎖

發布時間: 2022-07-09 03:12:06

㈠ 耗時的並發寫操作怎麼防止數據重復

如何處理大量數據並發操作

文件緩存資料庫緩存,優化sql,數據分流,資料庫表的橫向和縱向劃分,優化代碼結構!

鎖述的概
一. 為什麼要引入鎖
多個用戶同時對資料庫的並發操作時會帶來以下數據不一致的問題:

丟失更新
A,B兩個用戶讀同一數據並進行修改,其中一個用戶的修改結果破壞了另一個修改的結果,比如訂票系統

臟讀
A用戶修改了數據,隨後B用戶又讀出該數據,但A用戶因為某些原因取消了對數據的修改,數據恢復原值,此時B得到的數據就與資料庫內的數據產生了不一致

不可重復讀
A用戶讀取數據,隨後B用戶讀出該數據並修改,此時A用戶再讀取數據時發現前後兩次的值不一致

並發控制的主要方法是封鎖,鎖就是在一段時間內禁止用戶做某些操作以避免產生數據不一致

二 鎖的分類
鎖的類別有兩種分法:
1. 從資料庫系統的角度來看:分為獨占鎖(即排它鎖),共享鎖和更新鎖
MS-SQL Server 使用以下資源鎖模式。
鎖模式 描述
共享 (S) 用於不更改或不更新數據的操作(只讀操作),如 SELECT 語句。
更新 (U) 用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。
排它 (X) 用於數據修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進行多重更新。
意向鎖 用於建立鎖的層次結構。意向鎖的類型為:意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
架構鎖 在執行依賴於表架構的操作時使用。架構鎖的類型為:架構修改 (Sch-M) 和架構穩定性 (Sch-S)。
大容量更新 (BU) 向表中大容量復制數據並指定了 TABLOCK 提示時使用。

共享鎖
共享 (S) 鎖允許並發事務讀取 (SELECT) 一個資源。資源上存在共享 (S) 鎖時,任何其它事務都不能修改數據。一旦已經讀取數據,便立即釋放資源上的共享 (S) 鎖,除非將事務隔離級別設置為可重復讀或更高級別,或者在事務生存周期內用鎖定提示保留共享 (S) 鎖。

更新鎖
更新 (U) 鎖可以防止通常形式的死鎖。一般更新模式由一個事務組成,此事務讀取記錄,獲取資源(頁或行)的共享 (S) 鎖,然後修改行,此操作要求鎖轉換為排它 (X) 鎖。如果兩個事務獲得了資源上的共享模式鎖,然後試圖同時更新數據,則一個事務嘗試將鎖轉換為排它 (X) 鎖。共享模式到排它鎖的轉換必須等待一段時間,因為一個事務的排它鎖與其它事務的共享模式鎖不兼容;發生鎖等待。第二個事務試圖獲取排它 (X) 鎖以進行更新。由於兩個事務都要轉換為排它 (X) 鎖,並且每個事務都等待另一個事務釋放共享模式鎖,因此發生死鎖。

若要避免這種潛在的死鎖問題,請使用更新 (U) 鎖。一次只有一個事務可以獲得資源的更新 (U) 鎖。如果事務修改資源,則更新 (U) 鎖轉換為排它 (X) 鎖。否則,鎖轉換為共享鎖。

排它鎖
排它 (X) 鎖可以防止並發事務對資源進行訪問。其它事務不能讀取或修改排它 (X) 鎖鎖定的數據。

意向鎖
意向鎖表示 SQL Server 需要在層次結構中的某些底層資源上獲取共享 (S) 鎖或排它 (X) 鎖。例如,放置在表級的共享意向鎖表示事務打算在表中的頁或行上放置共享 (S) 鎖。在表級設置意向鎖可防止另一個事務隨後在包含那一頁的表上獲取排它 (X) 鎖。意向鎖可以提高性能,因為 SQL Server 僅在表級檢查意向鎖來確定事務是否可以安全地獲取該表上的鎖。而無須檢查表中的每行或每頁上的鎖 以確定事務是否可以鎖定整個表。

㈡ 怎麼實現springmvc多線程並發

知道Spring通過各種DAO模板類降低了開發者使用各種數據持久技術的難度。這些模板類都是線程安全的,也就是說,多個DAO可以復用同一個模板實例而不會發生沖突。 我們使用模板類訪問底層數據,根據持久化技術的不同,模板類需要綁定數據連接或會話的資源。但這些資源本身是非線程安全的,也就是說它們不能在同一時刻被多個線程共享。 雖然模板類通過資源池獲取數據連接或會話,但資源池本身解決的是數據連接或會話的緩存問題,並非數據連接或會話的線程安全問題。 按照傳統經驗,如果某個對象是非線程安全的,在多線程環境下,對對象的訪問必須採用synchronized進行線程同步。但Spring的DAO模板類並未採用線程同步機制,因為線程同步限制了並發訪問,會帶來很大的性能損失。 此外,通過代碼同步解決性能安全問題挑戰性很大,可能會增強好幾倍的實現難度。那模板類究竟仰丈何種魔法神功,可以在無需同步的情況下就化解線程安全的難題呢?答案就是ThreadLocal! ThreadLocal在Spring中發揮著重要的作用,在管理request作用域的Bean、事務管理、任務調度、AOP等模塊都出現了它們的身影,起著舉足輕重的作用。要想了解Spring事務管理的底層技術,ThreadLocal是必須攻克的山頭堡壘。 ThreadLocal是什麼 早在JDK1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal為解決多線程程序的並發問題提供了一種新的思路。使用這個工具類可以很簡潔地編寫出優美的多線程程序。 ThreadLocal很容易讓人望文生義,想當然地認為是一個「本地線程」。其實,ThreadLocal並不是一個Thread,而是Thread的局部變數,也許把它命名為ThreadLocalVariable更容易讓人理解一些。 當使用ThreadLocal維護變數時,ThreadLocal為每個使用該變數的線程提供獨立的變數副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。 從線程的角度看,目標變數就象是線程的本地變數,這也是類名中「Local」所要表達的意思。 線程局部變數並不是Java的新發明,很多語言(如IBM IBM XLFORTRAN)在語法層面就提供線程局部變數。在Java中沒有提供在語言級支持,而是變相地通過ThreadLocal的類提供支持。 所以,在Java中編寫線程局部變數的代碼相對來說要笨拙一些,因此造成線程局部變數沒有在Java開發者中得到很好的普及。 ThreadLocal的介面方法 ThreadLocal類介面很簡單,只有4個方法,我們先來了解一下: void set(Object value) 設置當前線程的線程局部變數的值。 public Object get() 該方法返回當前線程所對應的線程局部變數。 public void remove() 將當前線程局部變數的值刪除,目的是為了減少內存的佔用,該方法是JDK5.0新增的方法。需要指出的是,當線程結束後,對應該線程的局部變數將自動被垃圾回收,所以顯式調用該方法清除線程的局部變數並不是必須的操作,但它可以加快內存回收的速度。 protected Object initialValue() 返回該線程局部變數的初始值,該方法是一個protected的方法,顯然是為了讓子類覆蓋而設計的。這個方法是一個延遲調用方法,在線程第1次調用get()或set(Object)時才執行,並且僅執行1次。ThreadLocal中的預設實現直接返回一個null。 值得一提的是,在JDK5.0中,ThreadLocal已經支持泛型,該類的類名已經變為ThreadLocal<T>。API方法也相應進行了調整,新版本的API方法分別是voidset(T value)、T get()以及T initialValue()。 ThreadLocal是如何做到為每一個線程維護變數的副本的呢?其實實現的思路很簡單:在ThreadLocal類中有一個Map,用於存儲每一個線程的變數副本,Map中元素的鍵為線程對象,而值對應線程的變數副本。我們自己就可以提供一個簡單的實現版本: // 代碼清單1 SimpleThreadLocal class SimpleThreadLocal { private MapvalueMap = Collections.synchronizedMap(new HashMap()); public voidset(Object newValue) { valueMap.put(Thread.currentThread(), newValue);//①鍵為線程對象,值為本線程的變數副本 } publicObject get() { Thread currentThread = Thread.currentThread(); Object o = valueMap.get(currentThread);// ②返回本線程對應的變數 if (o == null &&!valueMap.containsKey(currentThread)) {// ③如果在Map中不存在,放到Map // 中保存起來。 o = initialValue(); valueMap.put(currentThread, o); } return o; } public voidremove() { valueMap.remove(Thread.currentThread()); } publicObject initialValue() { return null; } } 雖然代碼清單9?3這個ThreadLocal實現版本顯得比較幼稚,但它和JDK所提供的ThreadLocal類在實現思路上是相近的。 一個TheadLocal實例 下面,我們通過一個具體的實例了解一下ThreadLocal的具體使用方法 package threadLocalDemo; public class SequenceNumber { //①通過匿名內部類覆蓋ThreadLocal的initialValue()方法,指定初始值 privatestatic ThreadLocal<Integer> seqNum =new ThreadLocal<Integer>() { public Integer initialValue() { return 0; } }; //②獲取下一個序列值 public intgetNextNum() { seqNum.set(seqNum.get() + 1); return seqNum.get(); } publicstatic void main(String[] args) { SequenceNumber sn = new SequenceNumber(); // ③ 3個線程共享sn,各自產生序列號 TestClient t1 = new TestClient(sn); TestClient t2 = new TestClient(sn); TestClient t3 = new TestClient(sn); t1.start(); t2.start(); t3.start(); } privatestatic class TestClient extends Thread { private SequenceNumber sn; public TestClient(SequenceNumber sn) { this.sn = sn; } public void run() { for (int i = 0; i < 3; i++) { // ④每個線程打出3個序列值 System.out.println("thread[" + Thread.currentThread().getName()+"]sn[" + sn.getNextNum() + "]"); } } } } 通常我們通過匿名內部類的方式定義ThreadLocal的子類,提供初始的變數值,如例子中①處所示。TestClient線程產生一組序列號,在③處,我們生成3個TestClient,它們共享同一個SequenceNumber實例。運行以上代碼,在控制台上輸出以下的結果: thread[Thread-2] sn[1] thread[Thread-0] sn[1] thread[Thread-1] sn[1] thread[Thread-2] sn[2] thread[Thread-0] sn[2] thread[Thread-1] sn[2] thread[Thread-2] sn[3] thread[Thread-0] sn[3] thread[Thread-1] sn[3] 考察輸出的結果信息,我們發現每個線程所產生的序號雖然都共享同一個SequenceNumber實例,但它們並沒有發生相互干擾的情況,而是各自產生獨立的序列號,這是因為我們通過ThreadLocal為每一個線程提供了單獨的副本。 Thread同步機制的比較 ThreadLocal和線程同步機制相比有什麼優勢呢?ThreadLocal和線程同步機制都是為了解決多線程中相同變數的訪問沖突問題。 在同步機制中,通過對象的鎖機制保證同一時間只有一個線程訪問變數。這時該變數是多個線程共享的,使用同步機制要求程序慎密地分析什麼時候對變數進行讀寫,什麼時候需要鎖定某個對象,什麼時候釋放對象鎖等繁雜的問題,程序設計和編寫難度相對較大。 而ThreadLocal則從另一個角度來解決多線程的並發訪問。ThreadLocal會為每一個線程提供一個獨立的變數副本,從而隔離了多個線程對數據的訪問沖突。因為每一個線程都擁有自己的變數副本,從而也就沒有必要對該變數進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變數封裝進ThreadLocal。 由於ThreadLocal中可以持有任何類型的對象,低版本JDK所提供的get()返回的是Object對象,需要強制類型轉換。但JDK5.0通過泛型很好的解決了這個問題,在一定程度地簡化ThreadLocal的使用,代碼清單 9 2就使用了JDK5.0新的ThreadLocal<T>版本。 概括起來說,對於多線程資源共享的問題,同步機制採用了「以時間換空間」的方式,而ThreadLocal採用了「以空間換時間」的方式。前者僅提供一份變數,讓不同的線程排隊訪問,而後者為每一個線程都提供了一份變數,因此可以同時訪問而互不影響。 Spring使用ThreadLocal解決線程安全問題 我們知道在一般情況下,只有無狀態的Bean才可以在多線程環境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域。就是因為Spring對一些Bean(如RequestContextHolder、、LocaleContextHolder等)中非線程安全狀態採用ThreadLocal進行處理,讓它們也成為線程安全的狀態,因為有狀態的Bean就可以在多線程中共享了。 一般的Web應用劃分為展現層、服務層和持久層三個層次,在不同的層中編寫對應的邏輯,下層通過介面向上層開放功能調用。在一般情況下,從接收請求到返回響應所經過的所有程序調用都同屬於一個線程,如圖9?2所示: 圖1同一線程貫通三層 這樣你就可以根據需要,將一些非線程安全的變數以ThreadLocal存放,在同一次請求響應的調用線程中,所有關聯的對象引用到的都是同一個變數。 下面的實例能夠體現Spring對有狀態Bean的改造思路: 代碼清單3 TopicDao:非線程安全 public class TopicDao { private Connection conn;①一個非線程安全的變數 public void addTopic(){ Statement stat = conn.createStatement();②引用非線程安全變數 … } } 由於①處的conn是成員變數,因為addTopic()方法是非線程安全的,必須在使用時創建一個新TopicDao實例(非singleton)。下面使用ThreadLocal對conn這個非線程安全的「狀態」進行改造: 代碼清單4 TopicDao:線程安全 package threadLocalDemo; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; public class SqlConnection { //①使用ThreadLocal保存Connection變數 privatestatic ThreadLocal<Connection>connThreadLocal = newThreadLocal<Connection>(); publicstatic Connection getConnection() { // ②如果connThreadLocal沒有本線程對應的Connection創建一個新的Connection, // 並將其保存到線程本地變數中。 if (connThreadLocal.get() == null) { Connection conn = getConnection(); connThreadLocal.set(conn); return conn; } else { return connThreadLocal.get(); // ③直接返回線程本地變數 } } public voidaddTopic() { // ④從ThreadLocal中獲取線程對應的Connection try { Statement stat = getConnection().createStatement(); } catch (SQLException e) { e.printStackTrace(); } } }

㈢ java處理高並發時,使用synchronized代碼鎖防止同時對資料庫某一數據的問題。

首先synchronized不可能做到對某條資料庫的數據加鎖。它能做到的只是對象鎖。
比如數據表table_a中coloum_b的數據是臨界數據,也就是你說的要保持一致的數據。你可以定義一個類,該類中定義兩個方法read()和write()(注意,所有有關該臨界資源的操作都定義在這個類中),再定義一個靜態變數作為鎖就可以了。

public static final String LOCK = "table_a_b_lock";

public int read(){
synchronized LOCK{
System.out.println("read data...");
}
}

public void write(String data){
synchronized LOCK{
System.out.println("write data:" + data);
}
}

另外,還可以在資料庫級別加上鎖。資料庫本來就支持不同的隔離級別。

㈣ 文件鎖 資料庫鎖 緩存鎖哪個更快

這個模式在並發量並非太高或數據操作效率很高的情況下基本沒有什麼問題。
但是也許你已經看到了,if(緩存失效 && 恰好遇到並發量很高 && 資料庫操作時間長) then?
1. 緩存失效
2. 第一個進程去資料庫獲取新數據,假如包括SQL+程序邏輯耗時5S
3. 這5S內,第二個、第三個...第N個都只是獲取到已失效的緩存,於是也都連接資料庫...
4. 結果顯而易見,資料庫鎖表 -> 資料庫累計大量進程 -> 直至資料庫掛掉!

那麼,如何去解決這個問題呢?其實最簡單的方案就是:
添加一個標記,類似文件鎖,用於判斷此時程序是否正在更新緩存。
若是,則直接返回舊緩存(標記有設置失效時間,避免由於程序錯誤導致標記未刪除而引起的緩存不更新問題)
若否,則設置一個標記,然後進行數據獲取及緩存更新,最後刪除標記。

㈤ 有哪些Java web里的並發框架,都有哪些

一、並發是一種需求,以下先介紹一下javaweb對於高並發的處理思路:

1、synchronized 關鍵字

可用來給對象和方法或者代碼塊加鎖,當它鎖定一個方法或者一個代碼塊的時候,同一時刻最多隻有一個線程執行這段代碼。可能鎖對象包括: this, 臨界資源對象,Class 類對象

2、同步方法

同步方法鎖定的是當前對象。當多線程通過同一個對象引用多次調用當前同步方法時, 需同步執行。

3、同步代碼塊

同步代碼塊的同步粒度更加細致,是商業開發中推薦的編程方式。可以定位到具體的同步位置,而不是簡單的將方法整體實現同步邏輯。在效率上,相對更高。

A)鎖定臨界對象

同步代碼塊在執行時,是鎖定 object 對象。當多個線程調用同一個方法時,鎖定對象不變的情況下,需同步執行。

B)鎖定當前對象

4、鎖的底層實現

Java 虛擬機中的同步(Synchronization)基於進入和退出管程(Monitor)對象實現。同步方法 並不是由 monitor enter 和 monitor exit 指令來實現同步的,而是由方法調用指令讀取運行時常量池中方法的 ACC_SYNCHRONIZED 標志來隱式實現的。

5、鎖的種類

Java 中鎖的種類大致分為偏向鎖,自旋鎖,輕量級鎖,重量級鎖。

鎖的使用方式為:先提供偏向鎖,如果不滿足的時候,升級為輕量級鎖,再不滿足,升級為重量級鎖。自旋鎖是一個過渡的鎖狀態,不是一種實際的鎖類型。

鎖只能升級,不能降級。

6、volatile 關鍵字

變數的線程可見性。在 CPU 計算過程中,會將計算過程需要的數據載入到 CPU 計算緩存中,當 CPU 計算中斷時,有可能刷新緩存,重新讀取內存中的數據。在線程運行的過程中,如果某變數被其他線程修改,可能造成數據不一致的情況,從而導致結果錯誤。而 volatile 修飾的變數是線程可見的,當 JVM 解釋 volatile 修飾的變數時,會通知 CPU,在計算過程中, 每次使用變數參與計算時,都會檢查內存中的數據是否發生變化,而不是一直使用 CPU 緩存中的數據,可以保證計算結果的正確。

更多、此外還有很多細節需要通過學習去了解和完善,此處就不一一列舉了。

二、並發框架

並發框架很多,如ExecutorService、RxJava、Disruptor、Akka等,具體選擇哪個(或者都不選擇)是根據項目需求選擇的,框架本身的差異並不大,基本都是如下模式

㈥ java高並發,如何解決,什麼方式解決,高並發

首先,為防止高並發帶來的系統壓力,或者高並發帶來的系統處理異常,數據紊亂,可以以下幾方面考慮:1、加鎖,這里的加鎖不是指加java的多線程的鎖,是指加應用所和資料庫鎖,應用鎖這邊通常是使用redis的setnx來做,其次加資料庫鎖,因為代碼中加了應用所,所以資料庫不建議加悲觀鎖(排他鎖),一般加樂觀鎖(通過設置一個seq_no來解決),這兩個鎖一般能解決了,最後做合理的流控,丟棄一部分請求也是必不可少的

㈦ 如何實現springMVC的多線程並發

實現springMVC的多線程並發:

1、ThreadLocal為解決多線程程序的並發問題提供了一種新的思路

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

㈧ 如何處理大量數據並發操作

處理大量數據並發操作可以採用如下幾種方法:

1.使用緩存:使用程序直接保存到內存中。或者使用緩存框架: 用一個特定的類型值來保存,以區別空數據和未緩存的兩種狀態。

2.資料庫優化:表結構優化;SQL語句優化,語法優化和處理邏輯優化;分區;分表;索引優化;使用存儲過程代替直接操作。

3.分離活躍數據:可以分為活躍用戶和不活躍用戶。

4.批量讀取和延遲修改: 高並發情況可以將多個查詢請求合並到一個。高並發且頻繁修改的可以暫存緩存中。

5.讀寫分離: 資料庫伺服器配置多個,配置主從資料庫。寫用主資料庫,讀用從資料庫。

6.分布式資料庫: 將不同的表存放到不同的資料庫中,然後再放到不同的伺服器中。

7.NoSql和Hadoop: NoSql,not only SQL。沒有關系型資料庫那麼多限制,比較靈活高效。Hadoop,將一個表中的數據分層多塊,保存到多個節點(分布式)。每一塊數據都有多個節點保存(集群)。集群可以並行處理相同的數據,還可以保證數據的完整性。

拓展資料:

大數據(big data),指無法在一定時間范圍內用常規軟體工具進行捕捉、管理和處理的數據集合,是需要新處理模式才能具有更強的決策力、洞察發現力和流程優化能力的海量、高增長率和多樣化的信息資產。

在維克托·邁爾-舍恩伯格及肯尼斯·庫克耶編寫的《大數據時代》中大數據指不用隨機分析法(抽樣調查)這樣捷徑,而採用所有數據進行分析處理。大數據的5V特點(IBM提出):Volume(大量)、Velocity(高速)、Variety(多樣)、Value(低價值密度)、Veracity(真實性)。

㈨ java 怎樣處理高並發

一、背景綜述

並發就是可以使用多個線程或進程,同時處理(就是並發)不同的操作。

高並發的時候就是有很多用戶在訪問,導致系統數據不正確、糗事數據的現象。對於一些大型網站,比如門戶網站,在面對大量用戶訪問、高並發請求方面,基本的解決方案集中在這樣幾個環節:使用高性能的伺服器、高性能的資料庫、高效率的編程語言、還有高性能的Web容器。這幾個解決思路在一定程度上意味著更大的投入。

使用一般的synchronized或者是lock或者是隊列都是無法滿足高並發的問題。

二、解決方法有三:

1.使用緩存

2.使用生成靜態頁面

html純靜態頁面是效率最高、消耗最小的頁面。我們可以使用信息發布系統來實現簡單的信息錄入自動生成靜態頁面,頻道管理、許可權管理和自動抓取等功能,對於一個大型網站來說,擁有一套高效、可管理的信息發布系統CMS是必不可少的。

3.圖片伺服器分離

圖片是最消耗資源的,僵圖片和頁面分離可以降低提供頁面訪問請求的伺服器系統壓力,並且可以保證系統不會因為圖片問題而崩潰。

3.寫代碼的時候減少不必要的資源浪費:

  • 不要頻繁得使用new對象,對於在整個應用中只需要存在一個實例的類使用單例模式.對於String的連接操作,使用StringBuffer或者StringBuilder.對於utility類型的類通過靜態方法來訪問。

  • 避免使用錯誤的方式,如Exception可以控制方法推出,但是Exception要保留stacktrace消耗性能,除非必要不要使用 instanceof做條件判斷,盡量使用比的條件判斷方式.使用JAVA中效率高的類,比如ArrayList比Vector性能好。)

  • 使用線程安全的集合對象vector hashtable

  • 使用線程池