亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

具有共享整數對象的線程未按預期工作

具有共享整數對象的線程未按預期工作

慕斯709654 2022-06-23 19:23:48
我有一個問題,我必須以這種格式打印數字。First  1First  2Second  3Second  4First  5First  6Second  7Second  8First  9and so on...我已經實現了我的可運行接口,如下所示。class ThreadDemo implements Runnable { public volatile Integer num; public Object lock; public ThreadDemo(Integer num, Object lock) {  this.num = num;  this.lock = lock; } @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 { private static volatile Integer num = new Integer(1); public static void main(String...args) {  Object lock = new Object();  Thread thread1 = new Thread(new ThreadDemo(num, lock), "First");  thread1.start();  Thread thread2 = new Thread(new ThreadDemo(num, lock), "Second");  thread2.start(); }}當我運行程序時,我得到如下輸出First  1First  2Second  1Second  2First  3First  4Second  3Second  4而不是之前預期的結果。但是當我將整數更改為原子整數類型時,我開始得到預期的結果。誰能解釋我可以做些什么來使它使用整數而不是使用原子整數運行
查看完整描述

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;

}


查看完整回答
反對 回復 2022-06-23
?
胡子哥哥

TA貢獻1825條經驗 獲得超6個贊

僅就您的知識而言,您可能希望嘗試使用(s) (例如) 及其相關聯的 (s),而不是在 上使用synchronized塊。ObjectLockReentrantLockCondition

使用Condition(s) 您可以在線程之間以互斥的方式管理共享資源。


查看完整回答
反對 回復 2022-06-23
?
縹緲止盈

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


查看完整回答
反對 回復 2022-06-23
  • 3 回答
  • 0 關注
  • 125 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號