since this is my first question ever on stackoverflow, I will try to explain it as good as possible.
I am sorry if this is a duplicate question, but I spent a lot of time searching and couldn't find an answer to this. Since i started learning Threads not so long ago I came upon an obstacle now:DI want to code a NOT thread safe method, using two threads to increment and decrement an integer at the same time.
so my code so far is this .. sadly is not working and i don't know why
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;
}
}
And that's the class I use to test it.
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();
}
}
and the results are something like this ...
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..
So as u can see the threads are still not synchronised and i don't understand why:(
To ensure the atomicity of an increment/decrement operation you can should us an AtomicInteger
instead.
In your case to ensure the atomicity, instead of incrementing
/ decrementing
and then getting
the value which are not done atomically as they are not done within the same synchronized block, you should only use one method to do both like this:
public synchronized int changeNumber(boolean command){
this.command = command;
if (command){
counter++;
} else {
counter--;
}
return counter;
}
Then your code executed by the threads will be:
while(o.getCounter() < 100) {
System.out.println(
"Thread: " + Thread.currentThread().getId() + " counter: " + o.changeNumber(true)
);
}
and
while(o.getCounter() > -100) {
System.out.println(
"Thread: " + Thread.currentThread().getId() + " counter: " + o.changeNumber(false)
);
}
To make it it non thread safe, remove the synchronized
keyword.
public void changeNumber(boolean command){
if(command){
counter++;
}else{
counter--;
}
}
Each thread repeats increment/decrement and print. But another thread can run between increment/decrement and print like this.
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
If you want to avoid this, you should synchronize increment/decrement and print like this.
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);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.