簡體   English   中英

“同步功能”與“功能內部的同步塊”之間在功能上有什么區別嗎?

[英]Is there any functional difference between a 'synchronized function' and a 'synchronized block inside the function'?

兩者之間有什么區別:

public void synchronized func() {
}

public void func() {
   synchronized(this) {
   }
}

我知道在第一種情況下,整個函數func是同步的,而在第二種情況下,僅函數代碼的一部分是同步的。 但這有區別嗎? 我的意思是指令總是一個接一個地執行。 如果線程到達同步塊時無法獲取鎖,那將不是在同步塊之后開始操作!

在功能上有什么不同嗎?還是只是一個好習慣?

在第二種情況下,僅部分功能代碼被同步。 但這有區別嗎?

是的,如果在同步部分之外有很多代碼,這的確會有所作為。

public void func() {
   someHeavyOperations();
   synchronized(this) {
      criticalSectionOperations();
   }
   someMoreHeavyOperations();
}

您想使關鍵部分盡可能小。

如果線程到達同步塊時無法獲取鎖,那將不是在同步塊之后開始操作!

否,但是它將能夠在同步塊之前完成操作,並且在同步塊之后執行操作時也不會使任何人等待。

即使有同步塊外沒有更多的代碼,構建體是有用的,因為你可以在其他事情比同步this ,例如保持鎖定私人或更精細

我認為以上內容沒有任何實際差異。

但是 ,我傾向於后者,因為它更靈活。 除了鎖定包含對象( this )之外,您還可以鎖定特定的鎖定對象,並且不同的方法可以指定不同的鎖定對象(取決於同步要求)。 這意味着您可以在需要時將同步調整為更細粒度。

例如

public synchronized void doSomething() {
   ...
}

this鎖定)

public void doSomething() {
   synchronized(someLockObject) {
      ...
   }
}

從鎖定的角度來看,沒有區別。

從字節碼的角度來看,您可以告訴第一種方法是使用反射或大多數類查看器進行同步的。 第二種情況很難確定是這種情況。

如果要隱藏使用的鎖(即您不使用this鎖),則塊同步是首選的,這樣調用者就不會感到困惑。

您需要使“ Critical Section as small as possible. so synchronized(this) is more useful Critical Section as small as possible. so synchronized(this) is more useful

但是,如果您的關鍵部分是您的方法,那么您可以繼續並將該方法聲明為已synchronized

從1.5開始,您可以始終使用ReentrantLock

可重入互斥鎖,具有與使用同步方法和語句訪問的隱式監視鎖相同的基本行為和語義,但具有擴展功能。

class X {
private final ReentrantLock lock = new ReentrantLock();
// ...

public void m() { 
  lock.lock();  // block until condition holds
  try {
    // ... method body
  } finally {
    lock.unlock()
  }
}
}

如果您要同步方法的全部內容,則不會有功能上的差異。 如果僅同步方法的一部分,則同步化的范圍會有所不同。

您是正確的,同步塊之后的代碼將不會在同步塊之前執行。 但是,可以在任何不同步的點上換出線程。 考慮以下:

synchronized (this) {
    //sycnronized bit
}
// some other code

如果有兩個線程,則A&B和A獲取鎖B將會阻塞,直到A退出同步塊。 但是,一旦退出該塊,就可以將其換出。 然后,B可以進入同步塊並完成功能,然后再換回A。

這可以非常普遍地使用,例如,確保可變實例變量在計算范圍內保持一致,同時允許多個線程執行昂貴的計算。 例如

Object localCopy;
synchronized (this) {
    localCopy = this.instanceVar;
}
// expensive calculation using localCopy which won't change even if instanceVar is changed.

引用JLS http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.3.6

因此,代碼:

synchronized void bump() {
    count++;
}

具有與以下功能完全相同的效果:

void bump() {
    synchronized (this) { count++; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM