3 回答

TA貢獻1811條經驗 獲得超5個贊
如果將方法聲明為已同步(就像通過鍵入所做的那樣public synchronized void addA()),則會在整個對象上進行同步,因此,從同一對象訪問不同變量的兩個線程將始終相互阻塞。
如果您一次只想同步一個變量,那么兩個線程在訪問不同變量時不會互相阻塞,您可以分別以synchronized ()塊同步。如果a和b是對象引用,則可以使用:
public void addA() {
synchronized( a ) {
a++;
}
}
public void addB() {
synchronized( b ) {
b++;
}
}
但是由于它們是原始類型,所以您不能這樣做。
我建議您改用AtomicInteger:
import java.util.concurrent.atomic.AtomicInteger;
class X {
AtomicInteger a;
AtomicInteger b;
public void addA(){
a.incrementAndGet();
}
public void addB(){
b.incrementAndGet();
}
}

TA貢獻2039條經驗 獲得超8個贊
為此,在方法聲明上同步的是語法糖:
public void addA() {
synchronized (this) {
a++;
}
}
在靜態方法上,它是語法糖:
ClassA {
public static void addA() {
synchronized(ClassA.class) {
a++;
}
}
我認為,如果Java設計人員知道了現在對同步的了解,他們將不會添加語法糖,因為它經常會導致并發的不良實現。

TA貢獻1785條經驗 獲得超4個贊
從“ Java?教程”中的同步方法開始:
首先,不可能對同一對象的兩次同步方法調用進行交織。當一個線程正在執行對象的同步方法時,所有其他調用同一對象塊的同步方法的線程(掛起執行),直到第一個線程對該對象完成。
在同步塊上的“ Java?教程”中:
同步語句對于通過細粒度同步提高并發性也很有用。例如,假設類MsLunch有兩個實例字段c1和c2,它們從未一起使用。這些字段的所有更新都必須同步,但是沒有理由阻止c1更新與c2更新交織 —這樣做會通過創建不必要的阻塞來減少并發性。代替使用同步方法或以其他方式使用與此關聯的鎖,我們僅創建兩個對象來提供鎖。
(強調我的)
假設您有2個非交織變量。因此,您希望同時從不同的線程訪問每個線程。您需要定義鎖不上對象類本身,而是對類對象像下面(例如,從第二個Oracle鏈接):
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
添加回答
舉報