3 回答

TA貢獻1856條經驗 獲得超17個贊
Java Integer 不能通過引用傳遞。在您的代碼中,每個線程都會創建變量的副本。但是 atomicInteger 可以通過引用傳遞。
此外,為了獲得正確的結果,您可以將 num 變量更改為靜態變量。
public static Integer num = 1;
public Object lock;
public ThreadDemo(Integer num, Object lock) {
//this.num = num;
this.lock =lock;
}

TA貢獻1825條經驗 獲得超6個贊
僅就您的知識而言,您可能希望嘗試使用(s) (例如) 及其相關聯的 (s),而不是在 上使用synchronized
塊。Object
Lock
ReentrantLock
Condition
使用Condition
(s) 您可以在線程之間以互斥的方式管理共享資源。

TA貢獻2041條經驗 獲得超4個贊
我仍然認為這個問題沒有得到正確回答。這里的缺陷是您從未將共享數據標記為static. 所以每個線程都有自己獨立的副本。Integer是一個不可變的包裝類,這是真的,但在這種情況下它沒有任何關系。讓我們深入研究一下num++。該++運算符僅適用于(原始)整數類型。在幕后,num拆箱,++應用,然后將結果分配回num(在裝箱轉換之后)。該類Integer沒有++運算符。事實上,Integer對象是不可變的。
不可變意味著每次你增加并創建一個新的值對象。并且該新值對象被分配回您的num引用。但是兩個線程有自己的num引用副本,指向不同的Integer盒裝原語。因此,它們彼此獨立地增加它,而彼此不可見。如果你想在線程之間共享它,你必須static在聲明的地方使用訪問修飾符。將兩個值傳遞給共享變量是沒有意義的。相反,您可以內聯初始化它。這是固定版本。
public class ThreadDemo implements Runnable {
public static Integer num = 1;
public static final Object lock = new Object();
public ThreadDemo() {
}
@Override
public void run() {
try {
while (true) {
int count = 0;
synchronized (lock) {
Thread.sleep(100);
while (count < 2) {
System.out.println(Thread.currentThread().getName() + " " + num++);
count++;
}
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CoWorkingThreads {
public static void main(String[] args) {
Thread thread1 = new Thread(new ThreadDemo(), "First");
thread1.start();
Thread thread2 = new Thread(new ThreadDemo(), "Second");
thread2.start();
}
}
最后使用客戶端提供的鎖對象違反了同步策略的封裝。所以我改用了內部私有鎖對象。
這是新的輸出。
第一 1 第一 2 第二 3 第二 4 第一 5 第一 6 第二 7 第二 8 第一 9 第一 10
添加回答
舉報