導航:首頁 > 編程語言 > java同步關鍵字

java同步關鍵字

發布時間:2023-01-21 13:07:11

java 被關鍵字 synchronized修飾的方法有什麼特點關鍵字synchronized有什麼作用

Java語言的synchronized關鍵字,當它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多隻有一個線程執行該段代碼。

一、當兩個並發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以後才能執行該代碼塊。

二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。

三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

四、第三個例子同樣適用其它同步代碼塊。也就是說,當一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞。

❷ java線程同步問題,用了synchronized關鍵字後不能實現鎖定

你要把你的Timer t=new Timer()設置為static的,不然下面代碼中你創建兩個TestSync對象,也就有了兩個t,然後你的兩個線程分別調用不同的t,不能實現鎖定,下面是正確代碼
---------------------------------------------

public class TestSync extends Thread {
/**
* @param args
*/
static Timer t = new Timer();

public static void main(String[] args) {

TestSync t1 = new TestSync();
TestSync t2 = new TestSync();
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}

public void run() {
t.add(Thread.currentThread().getName());
}
}

class Timer {
private static int num = 0;

public synchronized void add(String name) {

num++;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {

}
System.out.println(name + "你是第" + num + "個訪問Timer的線程");

}

}

❸ java多線程開發的同步機制有哪些

Java同步
標簽: 分類:

一、關鍵字:

thread(線程)、thread-safe(線程安全)、intercurrent(並發的)

synchronized(同步的)、asynchronized(非同步的)、

volatile(易變的)、atomic(原子的)、share(共享)

二、總結背景:

一次讀寫共享文件編寫,嚯,好傢伙,竟然揪出這些零碎而又是一路的知識點。於是乎,Google和翻閱了《Java參考大全》、《Effective Java Second Edition》,特此總結一下供日後工作學習參考。

三、概念:

1、 什麼時候必須同步?什麼叫同步?如何同步?

要跨線程維護正確的可見性,只要在幾個線程之間共享非 final 變數,就必須使用 synchronized(或 volatile)以確保一個線程可以看見另一個線程做的更改。

為了在線程之間進行可靠的通信,也為了互斥訪問,同步是必須的。這歸因於java語言規范的內存模型,它規定了:一個線程所做的變化何時以及如何變成對其它線程可見。

因為多線程將非同步行為引進程序,所以在需要同步時,必須有一種方法強制進行。例如:如果2個線程想要通信並且要共享一個復雜的數據結構,如鏈表,此時需要
確保它們互不沖突,也就是必須阻止B線程在A線程讀數據的過程中向鏈表裡面寫數據(A獲得了鎖,B必須等A釋放了該鎖)。

為了達到這個目的,java在一個舊的的進程同步模型——監控器(Monitor)的基礎上實現了一個巧妙的方案:監控器是一個控制機制,可以認為是一個
很小的、只能容納一個線程的盒子,一旦一個線程進入監控器,其它的線程必須等待,直到那個線程退出監控為止。通過這種方式,一個監控器可以保證共享資源在
同一時刻只可被一個線程使用。這種方式稱之為同步。(一旦一個線程進入一個實例的任何同步方法,別的線程將不能進入該同一實例的其它同步方法,但是該實例
的非同步方法仍然能夠被調用)。

錯誤的理解:同步嘛,就是幾個線程可以同時進行訪問。

同步和多線程關系:沒多線程環境就不需要同步;有多線程環境也不一定需要同步。

鎖提供了兩種主要特性:互斥(mutual exclusion) 和可見性(visibility)。

互斥即一次只允許一個線程持有某個特定的鎖,因此可使用該特性實現對共享數據的協調訪問協議,這樣,一次就只有一個線程能夠使用該共享數據。

可見性要更加復雜一些,documents它必須確保釋放鎖之前對共享數據做出的更改對於隨後獲得該鎖的另一個線程是可見的 —— 如果沒有同步機制提供的這種可見性保證,線程看到的共享變數可能是修改前的值或不一致的值,這將引發許多嚴重問題

小結:為了防止多個線程並發對同一數據的修改,所以需要同步,否則會造成數據不一致(就是所謂的:線程安全。如java集合框架中Hashtable和
Vector是線程安全的。我們的大部分程序都不是線程安全的,因為沒有進行同步,而且我們沒有必要,因為大部分情況根本沒有多線程環境)。

2、 什麼叫原子的(原子操作)?

Java原子操作是指:不會被打斷地的操作。(就是做到互斥 和可見性?!)

那難道原子操作就可以真的達到線程安全同步效果了嗎?實際上有一些原子操作不一定是線程安全的。

那麼,原子操作在什麼情況下不是線程安全的呢?也許是這個原因導致的:java線程允許線程在自己的內存區保存變數的副本。允許線程使用本地的私有拷貝進
行工作而非每次都使用主存的值是為了提高性能(本人愚見:雖然原子操作是線程安全的,可各線程在得到變數(讀操作)後,就是各自玩
弄自己的副本了,更新操作(寫操作)因未寫入主存中,導致其它線程不可見)。

那該如何解決呢?因此需要通過java同步機制。

在java中,32位或者更少位數的賦值是原子的。在一個32位的硬體平台上,除了double和long型的其它原始類型通常都
是使用32位進行表示,而double和long通常使用64位表示。另外,對象引用使用本機指針實現,通常也是32位的。對這些32位的類型的操作是原
子的。

這些原始類型通常使用32位或者64位表示,這又引入了另一個小小的神話:原始類型的大小是由語言保證的。這是不對的。java語言保證的是原始類型的表
數范圍而非JVM中的存儲大小。因此,int型總是有相同的表數范圍。在一個JVM上可能使用32位實現,而在另一個JVM上可能是64位的。在此再次強
調:在所有平台上被保證的是表數范圍,32位以及更小的值的操作是原子的。

3、 不要搞混了:同步、非同步

舉個例子:普通B/S模式(同步)AJAX技術(非同步)

同步:提交請求->等待伺服器處理->處理完返回 這個期間客戶端瀏覽器不能幹任何事

非同步:請求通過事件觸發->伺服器處理(這是瀏覽器仍然可以作其他事情)->處理完畢

可見,彼「同步」非此「同步」——我們說的java中的那個共享數據同步(synchronized)

一個同步的對象是指行為(動作),一個是同步的對象是指物質(共享數據)。

4、 Java同步機制有4種實現方式:(部分引用網上資源)

① ThreadLocal ② synchronized( ) ③ wait() 與 notify() ④ volatile

目的:都是為了解決多線程中的對同一變數的訪問沖突
ThreadLocal
ThreadLocal 保證不同線程擁有不同實例,相同線程一定擁有相同的實例,即為每一個使用該變數的線程提供一個該變數值的副本,每一個線程都可以獨立改變自己的副本,而不是與其它線程的副本沖突。

優勢:提供了線程安全的共享對象

與其它同步機制的區別:同步機制是為了同步多個線程對相同資源的並發訪問,是為了多個線程之間進行通信;而 ThreadLocal 是隔離多個線程的數據共享,從根本上就不在多個線程之間共享資源,這樣當然不需要多個線程進行同步了。

volatile
volatile 修飾的成員變數在每次被線程訪問時,都強迫從共享內存中重讀該成員變數的值。而且,當成員變數發生變化時,強迫線程將變化值回寫到共享內存。
優勢:這樣在任何時刻,兩個不同的線程總是看到某個成員變數的同一個值。
緣由:Java
語言規范中指出,為了獲得最佳速度,允許線程保存共享成員變數的私有拷貝,而且只當線程進入或者離開同步代碼塊時才與共享成員變數的原
始值對比。這樣當多個線程同時與某個對象交互時,就必須要注意到要讓線程及時的得到共享成員變數的變化。而 volatile
關鍵字就是提示 VM :對於這個成員變數不能保存它的私有拷貝,而應直接與共享成員變數交互。
使用技巧:在兩個或者更多的線程訪問的成員變數上使用 volatile 。當要訪問的變數已在 synchronized 代碼塊中,或者為常量時,不必使用。

線程為了提高效率,將某成員變數(如A)拷貝了一份(如B),線程中對A的訪問其實訪問的是B。只在某些動作時才進行A和B的同步,因此存在A和B不一致
的情況。volatile就是用來避免這種情況的。
volatile告訴jvm,它所修飾的變數不保留拷貝,直接訪問主內存中的(讀操作多時使用較好;線程間需要通信,本條做不到)

Volatile 變數具有 synchronized 的可見性特性,但是不具備原子特性。這就是說線程能夠自動發現 volatile
變數的最新值。Volatile
變數可用於提供線程安全,但是只能應用於非常有限的一組用例:多個變數之間或者某個變數的當前值與修改後值
之間沒有約束。

您只能在有限的一些情形下使用 volatile 變數替代鎖。要使 volatile 變數提供理想的線程安全,必須同時滿足下面兩個條件:

對變數的寫操作不依賴於當前值;該變數沒有包含在具有其他變數的不變式中。

sleep() vs wait()
sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,把執行機會給其他線程,但是監控狀態依然保持,到時後會自動恢復。調用sleep不會釋放對象鎖。
wait是Object類的方法,對此對象調用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)後本線程才進入對象鎖定池准備獲得對象鎖進入運行狀態。

(如果變數被聲明為volatile,在每次訪問時都會和主存一致;如果變數在同步方法或者同步塊中被訪問,當在方法或者塊的入口處獲得鎖以及方法或者塊退出時釋放鎖時變數被同步。)

❹ java中 synchronized同步處理後 為什麼只有一個線程在運行

java中
synchronized同步處理後,代表該線程是同步的,即多線程訪問時,無法同時有兩個或以上線程進行訪問。具體的原理是,當第一個線程進入該同步代碼塊之後,會暫時獲得同步塊的鎖,當第二個線程進入時,由於第一個線程並未結束,同步代碼塊的鎖沒有釋放,所以第二個線程進不來,達到只有一個線程在運行的目的。synchronized同步處理通常用於封裝需要共享的可改變的數據,為了讓數據更安全所使用的技術。

❺ Java 線程同步幾種方式

(1)同步來方法:
即有synchronized關鍵字修飾的自方法。 由於java的每個對象都有一個內置鎖,當用此關鍵字修飾方法時,內置鎖會保護整個方法。在調用該方法前,需要獲得內置鎖,否則就處於阻塞狀態。
(2)同步代碼塊
即有synchronized關鍵字修飾的語句塊。被該關鍵字修飾的語句塊會自動被加上內置鎖,從而實現同步
(3)使用特殊域變數(Volatile)實現線程同步
a.volatile關鍵字為域變數的訪問提供了一種免鎖機制
b.使用volatile修飾域相當於告訴虛擬機該域可能會被其他線程更新
c.因此每次使用該域就要重新計算,而不是使用寄存器中的值
d.volatile不會提供任何原子操作,它也不能用來修飾final類型的變數
(4)使用重入鎖實現線程同步
在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。ReentrantLock類是可重入、互斥、實現了Lock介面的鎖, 它與使用synchronized方法和快具有相同的基本行為和語義,並且擴展了其能力。
(5)使用局部變數實現線程同步

❻ java 線程同步中synchronized關鍵字

一個對象的方法被線程調用的時候這個對象的其他方法被其他線程調用,這裡面完全沒有關系好吧
調用這個對象的鎖定的方法為什麼會鎖定其他方法呢

你想問的是一個方法被多個線程調用的問題吧,有可能會存在死鎖的情況

❼ java同步關鍵字有哪些

每一個對象都有來一把獨占鎖。自獨占鎖只限制線程對它的同步方法的訪問,對非同步方法,獨占鎖沒有意義。
synchronized是java中解決同步問題的一個方法。synchronized可以用來修飾方法,這樣的方法就是同步方法。一個對象里可以有任意多個同步方法。任意時間里只能有一個線程訪問這些同步方法。例如,現成T1在訪問同步方法M1,此時還有一個同步方法M2此時無人訪問,但是由於已經有一個線程正在訪問這個對象的同步方法M1,所以試圖訪問M2的線程將被阻塞。直到T1對M1的訪問結束。
可見同步方法有在一個同步方法運行期內保證只有一個線程能夠進入。一旦方法結束,裡面的線程就會失去對該對象的獨占權。
synchronized語句塊,可以指定要獲得哪個對象的獨占權,一旦獲得,在語塊執行過程中,線程會始終掌握該對象的獨占權。此時,它可以連續訪問多個該對象的同步方法。在整個過程中,獨占權都牢牢掌握在該線程手中,其它線程沒有任何機會。而如果沒有同步語句塊,則如果連續訪問某個對象的同步方法,則在前一個方法返回,到下一個方法調用的間隙內,其他線程有機會搶先獲得該對象的獨占權。

❽ java中線程同步的幾種方法

線程同步主要有以下種方法(示例中是實現計數的功能):

1、同步方法,即使用synchronized關鍵字修飾方法,例如:

publicsynchronizedvoidadd(intc){...}

2、同步代碼塊,即有synchronized關鍵字修飾的語句塊,例如:

publicvoidaddAndGet(intc){
synchronized(this){
count+=c;
}
}

3、使用特殊域變數(volatile)實現線程同步,該方法不能保證絕對的同步。

例如:privatevolatileintcount=0;

4、使用鎖實現線程同步,例如:

privateLocklock=newReentrantLock();
publicvoidadd(intc){
lock.lock();//上鎖
try{
count+=c;
}finally{
lock.unlock();//解鎖
}
}

5、使用原子變數實現線程同步,在java的util.concurrent.atomic包中提供了創建了原子類型變數的工具類,例如:

privateAtomicIntegercount=newAtomicInteger(1);
publicvoidadd(intc){
count.addAndGet(c);
}

6、使用局部變數實現線程同步,如果使用ThreadLocal管理變數,則每一個使用該變數的線程都獲得該變數的副本, 副本之間相互獨立,這樣每一個線程都可以隨意修改自己的變數副本,而不會對其他線程產生影響。

ThreadLocal 類的常用方法

new ThreadLocal<T>() : 創建一個線程本地變數

get() : 返回此線程局部變數的當前線程副本中的值

initialValue() : 返回此線程局部變數的當前線程的"初始值"

set(T value) : 將此線程局部變數的當前線程副本中的值設置為value

示例代碼:

privatestaticThreadLocal<Integer>count=newThreadLocal<Integer>(){
@Override
protectedIntegerinitialValue(){
return1;
}
};

publicvoidadd(intc){
count.set(count.get()+c);
}

7、使用阻塞隊列實現,例如LinkedBlockingQueue,具體使用可網路LinkedBlockingQueue的用法或查看java文檔。

❾ JAVA 中 同步方法的關鍵字,為什麼不推薦用 stop()和 suspend()

stop這個方法將終止所有未結束的方法,包括run方法。當一個線程停止時候,他會立即釋放所有他鎖住對象上的鎖。這會導致對象處於不一致的狀態。假如一個方法在將錢從一個賬戶轉移到另一個賬戶的過程中,在取款之後存款之前就停止了。那麼現在銀行對象就被破壞了。因為鎖已經被釋放了。當線程想終止另一個線程的時候,它無法知道何時調用stop是安全的,何時會導致對象被破壞。所以這個方法被棄用了。你應該中斷一個線程而不是停止他。
suspend不會破壞對象。但是,如果你用一個suspend掛起一個有鎖的線程,那麼在鎖恢復之前將不會被釋放。如果調用suspend的方法線程試圖取得相同的鎖,程序就會死鎖。

閱讀全文

與java同步關鍵字相關的資料

熱點內容
商品驗偽用什麼APP查 瀏覽:350
請問大數據與會計專業做什麼的 瀏覽:77
如何修改數據上年結轉 瀏覽:6
win7一直配置文件重啟 瀏覽:124
佳能ir2525i網路掃描 瀏覽:283
win10指紋無法識別 瀏覽:646
jsp中怎麼引入js文件 瀏覽:925
文件名構成部分 瀏覽:484
興國互聯網app有哪些 瀏覽:475
北京時間票房多少票房統計數據 瀏覽:750
探探文件夾是哪個 瀏覽:429
如何分類微信文件 瀏覽:446
城市天際線win10 瀏覽:813
運動APP跑步如何抓作弊 瀏覽:57
微信中秋節動態祝福語 瀏覽:703
練英語的網站哪個好 瀏覽:894
科來網路分析系統報價 瀏覽:437
哪裡可以上傳自己的php網站 瀏覽:373
安卓手機如何打開zx文件 瀏覽:531
app攻擊是什麼 瀏覽:888

友情鏈接