![](/img/trans.png)
[英]Java: Multiple threads decrementing static variable via synchronized method accessing variable at the same time
[英]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.