因为这是我在stackoverflow上的第一个问题,我将尝试尽可能好地解释它。
如果这是一个重复的问题,我很抱歉,但我花了很多时间搜索,但无法找到答案。 自从我不久前开始学习Threads以来,我现在遇到了一个障碍:D 我想编写一个NOT线程安全的方法,使用两个线程同时递增和递减一个整数。
所以到目前为止我的代码就是这个......遗憾的是没有用,我不知道为什么
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..
因为你可以看到线程仍未同步,我不明白为什么:(
答案 0 :(得分:1)
为了确保递增/递减操作的原子性,您可以改为使用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)
);
}
答案 1 :(得分:0)
要使其非线程安全,请删除synchronized
关键字。
public void changeNumber(boolean command){
if(command){
counter++;
}else{
counter--;
}
}
答案 2 :(得分:0)
每个线程重复递增/递减并打印。 但另一个线程可以在增量/减量和打印之间运行。
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);
}
}