導航:首頁 > 編程語言 > java線程安全的實現

java線程安全的實現

發布時間:2022-04-23 03:07:06

java如何實現線程安全,synchronized和lock的區別,可重入鎖

一、synchronized和lock的用法區別


synchronized:在需要同步的對象中加入此控制,synchronized在方法上,也在特定代碼塊中,括弧中表示需要鎖的對象。


lock:需要顯示指定起始位置和終止位置。一般使用ReentrantLock類做為鎖,多個線程中必須要使用一個ReentrantLock類做為對象才能保證鎖的生效。且在加鎖和解鎖處需要通過lock()和unlock()顯示指出。所以一般會在finally塊中寫unlock()以防死鎖。


二、synchronized和lock用途區別


synchronized原語和ReentrantLock在一般情況下沒有什麼區別,但是在非常復雜的同步應用中,請考慮使用ReentrantLock,特別是遇到下面2種需求的時候。


  1. 某個線程在等待一個鎖的控制權的這段時間需要中斷

  2. 2.需要分開處理一些wait-notify,ReentrantLock裡面的Condition應用,能夠控制notify哪個線程

  3. 3.具有公平鎖功能,每個到來的線程都將排隊等候

② JAVA 怎樣實現本地線程安全

欄位用final修飾,除非需要變化
變數用鎖來守護,一組作為不變數的變數要用同一把鎖
在復雜的組合操作中要保持鎖
文檔化你的同步策略
主要就這些,java里可以用synchronized關鍵字來進行鎖,也可以用並發包里提供的許多類來完成線程安全的操作

③ java中哪些線程安全

JAVA中線程安全的map有:Hashtable、synchronizedMap、ConcurrentHashMap。
java中map中線程安全怎麼實現:
1、同步的map就是Hashtable, concurrenthashmap。
2、你看到的Hashtable就是直接在hashmap上加了個鎖,concurrenthashmap就是分成多個分段鎖。
java代碼中線程安全級別:
1、絕對線程安全。
在任何環境下,調用者都不需要考慮額外的同步措施,都能夠保證程序的正確性。這個定義要求很嚴格,java裡面滿足這個要求的類比較少,對於實現jsr133規范(java內存模型)的jdk(一般指jdk5.0之上),一般的不變類都是滿足絕地線程安全的。比如 String,Integer類。一般情況下,定義了如果一個類裡面所有欄位都是final類型的,一般都認為這個類是不變的。不變類都是絕對線程安全的。
2、相對線程安全
在一般情況下,調用者都不需要考慮線程同步,大多數情況下,都能夠正常運行。jdk裡面大多數類都是相對安全的。最常見的例子是java裡面Vector類。

④ java多線程有幾種實現方法

⑤ java 如何實現一個線程安全的隊列

以下是兩個線程:

import java.util.*;

public class Thread_List_Operation {
//假設有這么一個隊列
static List list = new LinkedList();

public static void main(String[] args) {
Thread t;
t = new Thread(new T1());
t.start();
t = new Thread(new T2());
t.start();

}

}

//線程T1,用來給list添加新元素
class T1 implements Runnable{

void getElemt(Object o){
Thread_List_Operation.list.add(o);
System.out.println(Thread.currentThread().getName() + "為隊列添加了一個元素");
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
getElemt(new Integer(1));
}

}

}

//線程T2,用來給list添加新元素
class T2 implements Runnable{

void getElemt(Object o){
Thread_List_Operation.list.add(o);
System.out.println(Thread.currentThread().getName() + "為隊列添加了一個元素");
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
getElemt(new Integer(1));
}

}

}

//結果(亂序)
Thread-0為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素

⑥ Java的List如何實現線程安全

Java的List如何實現線程安全?

Collections.synchronizedList(names);效率最高,線程安全

Java的List是我們平時很常用的集合,線程安全對於高並發的場景也十分的重要,那麼List如何才能實現線程安全呢 ?


加鎖

首先大家會想到用Vector,這里我們就不討論了,首先討論的是加鎖,例如下面的代碼


public class Synchronized{

private List<String> names = new LinkedList<>();

public synchronized void addName(String name ){
names.add("abc");
}
public String getName(Integer index){
Lock lock =new ReentrantLock();
lock.lock();
try {
return names.get(index);
}catch (Exception e){
e.printStackTrace();
}
finally {
lock.unlock();
}
return null;
}
}

synchronized一加,或者使用lock 可以實現線程安全,但是這樣的List要是很多個,代碼量會大大增加。

java自帶類

在java中我找到自帶有兩種方法


CopyOnWriteArrayList

CopyOnWrite 寫入時復制,它使一個List同步的替代品,通常情況下提供了更好的並發性,並且避免了再迭代時候對容器的加鎖和復制。通常更適合用於迭代,在多插入的情況下由於多次的復制性能會一定的下降。


下面是add方法的源代碼


public boolean add(E e) {
final ReentrantLock lock = this.lock; // 加鎖 只允許獲得鎖的線程訪問
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
// 創建個長度加1的數組並復制過去
Object[] newElements = Arrays.Of(elements, len + 1);
newElements[len] = e; // 賦值
setArray(newElements); // 設置內部的數組
return true;
} finally {
lock.unlock();
}
}


Collections.synchronizedList

Collections中有許多這個系列的方法例如


主要是利用了裝飾者模式對傳入的集合進行調用 Collotions中有內部類SynchronizedList


static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;

final List<E> list;

SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}

static class SynchronizedCollection<E> implements Collection<E>, Serializable {
private static final long serialVersionUID = 3053995032091335093L;

final Collection<E> c; // Backing Collection
final Object mutex; // Object on which to synchronize


這里上面的mutex就是鎖的對象 在構建時候可以指定鎖的對象 主要使用synchronize關鍵字實現線程安全

/**
* @serial include
*/
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;

final List<E> list;

SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
這里只是列舉SynchronizedList ,其他類類似,可以看下源碼了解下。

測試
public class Main {
public static void main(String[] args) {
List<String> names = new LinkedList<>();
names.add("sub");
names.add("jobs");
// 同步方法1 內部使用lock
long a = System.currentTimeMillis();
List<String> strings = new CopyOnWriteArrayList<>(names);
for (int i = 0; i < 100000; i++) {
strings.add("param1");
}
long b = System.currentTimeMillis();
// 同步方法2 裝飾器模式使用 synchronized
List<String> synchronizedList = Collections.synchronizedList(names);
for (int i = 0; i < 100000; i++) {
synchronizedList.add("param2");
}
long c = System.currentTimeMillis();
System.out.println("CopyOnWriteArrayList time == "+(b-a));
System.out.println("Collections.synchronizedList time == "+(c-b));
}
}


兩者內部使用的方法都不一樣,CopyOnWriteArrayList內部是使用lock進行加鎖解鎖完成單線程訪問,synchronizedList使用的是synchronize

進行了100000次添加後時間對比如下:

可以看出來還是使用了synchronize的集合工具類在添加方面更加快一些,其他方法這里篇幅關系就不測試了,大家有興趣去試一下。

⑦ java中map中線程安全怎麼實現

同步的map就是Hashtable,
concurrenthashmap.
你看到的Hashtable就是直接在hashmap上加了個鎖,concurrenthashmap就是分成多個分段鎖。

⑧ Java線程安全的單例模式的幾種實現

四種線程安全的單例模式實現方式,其實並不局限於這四種,本文只是起一個拋磚引玉的作用。

⑨ 如何確保Java線程安全

在Java中可以有很多方法來保證線程安全——同步,使用原子類(atomicconcurrentclasses),實現並發鎖,使用volatile關鍵字,使用不變類和線程安全類。

⑩ Java中如何保證線程安全性

並發(concurrency)一個並不陌生的詞,簡單來說,就是cpu在同一時刻執行多個任務。

而Java並發則由多線程實現的。

在jvm的世界裡,線程就像不相乾的平行空間,串列在虛擬機中。(當然這是比較籠統的說法,線程之間是可以交互的,他們也不一定是串列。)

多線程的存在就是壓榨cpu,提高程序性能,還能減少一定的設計復雜度(用現實的時間思維設計程序)。

這么說來似乎線程就是傳說中的銀彈了,可事實告訴我們真正的銀彈並不存在。

多線程會引出很多難以避免的問題, 如死鎖,臟數據,線程管理的額外開銷,等等。更大大增加了程序設計的復雜度。

但他的優點依舊不可替代。

死鎖和臟數據就是典型的線程安全問題。

簡單來說,線程安全就是:在多線程環境中,能永遠保證程序的正確性。

只有存在共享數據時才需要考慮線程安全問題。

java內存區域:

其中,方法區和堆就是主要的線程共享區域。那麼就是說共享對象只可能是類的屬性域或靜態域。

了解了線程安全問題的一些基本概念後, 我們就來說說如何解決線程安全問題。我們來從一個簡單的servlet示例來分析:

1. 了解業務場景的線程模型

這里的線程模型指的是: 在該業務場景下, 可能出現的線程調用實況。

眾所周知,Servlet是被設計為單實例,在請求進入tomcat後,由Connector建立連接,再講請求分發給內部線程池中的Processor,

此時Servlet就處於一個多線程環境。即如果存在幾個請求同時訪問某個servlet,就可能會有幾個線程同時訪問該servlet對象。如圖:

線程模型,如果簡單的話,就在腦海模擬一下就好了,復雜的話就可以用紙筆或其他工具畫出來。

2. 找出共享對象

這里的共享對象就很明顯就是ReqCounterServlet。

3. 分析共享對象的不變性條件

不變性條件,這個名詞是在契約式編程的概念中的。不變性條件保證類的狀態在任何功能被執行後都保持在一個可接受的狀態。

這里可以引申出,不可變對象是線程安全的。(因為不可變對象就沒有不變性條件)

不變性條件則主要由對可變狀態的修改與訪問構成。

這里的servlet很簡單, 不變性條件大致可以歸納為: 每次請求進入時count計數必須加一,且計數必須正確。

在復雜的業務中, 類的不變性條件往往很難考慮周全。設計的世界是險惡的,只能小心謹慎,用測量去證明,最大程度地減少錯誤出現的幾率。

4. 用特定的策略解決線程安全問題。

如何解決的確是該流程的重點。目前分三種方式解決:

第一種,修改線程模型。即不在線程之間共享該狀態變數。一般這個改動比較大,需要量力而行。

第二種,將對象變為不可變對象。有時候實現不了。

第三種,就比較通用了,在訪問狀態變數時使用同步。 synchronized和Lock都可以實現同步。簡單點說,就是在你修改或訪問可變狀態時加鎖,獨占對象,讓其他線程進不來。

這也算是一種線程隔離的辦法。(這種方式也有不少缺點,比如說死鎖,性能問題等等)

其實有一種更好的辦法,就是設計線程安全類。《代碼大全》就有提過,問題解決得越早,花費的代價就越小。

是的,在設計時,就考慮線程安全問題會容易的多。

首先考慮該類是否會存在於多線程環境。如果不是,則不考慮線程安全。

然後考慮該類是否能設計為不可變對象,或者事實不可變對象。如果是,則不考慮線程安全

最後,根據流程來設計線程安全類。

設計線程安全類流程:

1、找出構成對象狀態的所有變數。

2、找出約束狀態變數的不變性條件。

3、建立對象狀態的並發訪問管理策略。

有兩種常用的並發訪問管理策略:

1、java監視器模式。 一直使用某一對象的鎖來保護某狀態。

2、線程安全委託。將類的線程安全性委託給某個或多個線程安全的狀態變數。(注意多個時,這些變數必須是彼此獨立,且不存在相關聯的不變性條件。)

閱讀全文

與java線程安全的實現相關的資料

熱點內容
數控銑床法蘭克子程序編程 瀏覽:173
linux打包命令targz 瀏覽:996
抖音app是哪個 瀏覽:407
蘋果app怎麼上架 瀏覽:255
NA伺服器地址 瀏覽:427
我的世界如何初始化伺服器 瀏覽:97
哪個手機app天氣預報最准 瀏覽:752
怎樣把視頻壓縮至25m 瀏覽:570
vivox27文件夾怎麼改變 瀏覽:727
新手玩狼人殺用什麼app 瀏覽:615
pdf在線查看 瀏覽:954
安卓tv90如何關閉後台 瀏覽:683
php讀取word亂碼 瀏覽:755
minicom源碼 瀏覽:1001
海爾冷櫃壓縮機 瀏覽:416
聯通伺服器如何調試信號 瀏覽:136
stata新命令 瀏覽:941
單調棧演算法python 瀏覽:606
微信解壓游戲怎麼下載 瀏覽:962
忍三伺服器不同如何登上賬號 瀏覽:822