簡體   English   中英

Java線程同時遞增和遞減int

[英]Java Threads incrementing and decrementing an int at the same time

因為這是我有關stackoverflow的第一個問題,所以我將盡力解釋它。

很抱歉,如果這是一個重復的問題,但我花了很多時間進行搜索,卻找不到答案。 由於我不久前才開始學習線程,所以現在遇到了一個障礙:DI想編寫一個非線程安全的方法,使用兩個線程同時遞增和遞減一個整數。

所以到目前為止我的代碼是..可悲的是無法正常工作,我不知道為什么

public class  ThreadFunctions {
    private  int counter = 0;
    private boolean command =  false;

    public synchronized void changeNumber(boolean command){
        this.command = command;
        synchronized (this) {
            if(command){
                counter++;
            }else{
                counter--;
            }
        }
    }

    public synchronized int getCounter(){
        return this.counter;
    }
}

這就是我用來測試它的類。

 public class Demo{
    public static void main(String[] args){

    final ThreadFunctions o =  new ThreadFunctions();

    new Thread(new Runnable() {
        @Override
        public void run() {
            while(o.getCounter() < 100){
                o.changeNumber(true);
                System.out.println("Thread: " + Thread.currentThread().getId() + " counter: "+o.getCounter());
            }
        }
    }).start();

    new Thread(new Runnable() {
        @Override
        public void run() {
            while(o.getCounter() > -100){
                o.changeNumber(false);
                System.out.println("Thread: " + Thread.currentThread().getId() + " counter: "+ o.getCounter());
            }
        }
    }).start();
    }
}

結果是這樣的...

Thread: 10 counter: 5
Thread: 10 counter: 6
Thread: 10 counter: 7
Thread: 10 counter: 8
Thread: 10 counter: 9
Thread: 11 counter: 8
Thread: 10 counter: 9
Thread: 10 counter: 10
Thread: 10 counter: 11
Thread: 10 counter: 11
Thread: 10 counter: 12
Thread: 10 counter: 13
Thread: 11 counter: 13

etc..

因此,如您所見,線程仍未同步,我不明白為什么:(

為了確保遞增/遞減操作的原子性,您可以改為使用AtomicInteger

在您的情況下,為了確保原子性,而不是incrementing / decrementing然后getting未在同一同步塊中完成的原子地完成的值,您應該僅使用一種方法來做到這兩個:

public synchronized int changeNumber(boolean command){
    this.command = command;
    if (command){
        counter++;
    } else {
        counter--;
    }
    return counter;
}

然后,線程執行的代碼將是:

while(o.getCounter() < 100) {
    System.out.println(
        "Thread: " + Thread.currentThread().getId() + " counter: " + o.changeNumber(true)
    );
}

while(o.getCounter() > -100) {
    System.out.println(
        "Thread: " + Thread.currentThread().getId() + " counter: " + o.changeNumber(false)
    );
}

要使其成為非線程安全的,請刪除synchronized關鍵字。

 public void changeNumber(boolean command){
            if(command){
                counter++;
            }else{
                counter--;
        }
    }

每個線程重復遞增/遞減和打印。 但是另一個線程可以在增量/減量之間運行,並像這樣打印。

OUTPUT                   THREAD 10   THREAD 11  COUNTER
----------------------   ---------   ---------  -------
Thread: 10 counter: 9    print                      9
                         increment                 10
Thread: 10 counter: 10   print                     10
                         increment                 11
Thread: 10 counter: 11   print                     11
                                     decrement     10
                         increment                 11
Thread: 10 counter: 11   print                     11
                         increment                 12
Thread: 10 counter: 12   print                     12
                         increment                 13
Thread: 10 counter: 13   print                     13
Thread: 11 counter: 13               print         13

如果要避免這種情況,則應同步增量/減量並像這樣打印。

    public synchronized void changeNumber(boolean command) {
        this.command = command;
        synchronized (this) {
            if (command) {
                counter++;
            } else {
                counter--;
            }
            System.out.println("Thread: " + Thread.currentThread().getId() + " counter: " + counter);
        }
    }

暫無
暫無

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

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