3

I know that concurrently accessing the same object from different threads, without synchronisation, is in general a bad thing. But what about this case:

I have multiple threads running (consider two, ThreadA & ThreadB). I also have this static class to keep count of the number of times a Thread does something.

public class Counter {
  static private int counter=0;
  static public void incCounter() {
    counter++;
  }
}

What happens if ThreadA and ThreadB both call Counter.incCounter()?

6
  • nothing disastrous, but the counter will not be accurate sum. Commented Jul 22, 2010 at 18:13
  • @irreputable: depends on what you consider "disastrous". If something critical depends on the counter, it will fail. Commented Jul 22, 2010 at 18:23
  • Why is accessing the same object from different threads a bad thing? If it's needed then it's necessary. Commented Jul 22, 2010 at 18:59
  • @Steve Kuo - question clarified to state that unsynchronised concurrent access is whats bad. Obviously properly coordinated access from multiple threads is not. Commented Jul 22, 2010 at 19:49
  • For light weight performance counters, I don't use any kind of thread safety in the knowledge that the counter might be slightly out, but it will be of the lowest cost. The counter is just used as an indication. Commented Jul 22, 2010 at 21:46

5 Answers 5

11

It's not safe.

Each thread will attempt to read counter, add one to it, and write back the result. You're not guaranteed what order these reads and writes happen in, or even if the results are visible to each thread.

In particular, one failure case would be that each thread reads the value 0, increments it to 1, and writes back the value 1. This would give the counter the value 1 even after two threads attempted to increment it.

Consider using AtomicInteger.incrementAndGet() instead.

Sign up to request clarification or add additional context in comments.

1 Comment

Huh, never knew it existed. Every day's a school day on SO. Thanks.
1

Its value will either be 1 or 2. There's no difference between static and non static variables in this context.

Comments

0

It doesn't matter whether it's a static object or an instance: if you change it from multiple threads, you're going to have a problem.

Comments

0

to avoid conflict use the keyword synchronized.

public class Counter {
  static private int counter=0;
  public static synchronized void incCounter() {
      counter++;
  }
}

this keywords allows only one thread for time to call incCounter().

1 Comment

This will work but is inefficient compared to AtomicInteger.
0

Dave is correct, but a quick fix is just to add the "synchronized" keyword to that method description; if multiple threads call that method, they will block at the method boundary until the one inside (that won the race) increments and exists, then the 2nd caller will enter.

This is a lot like designing a good "getInstance()" method on a Singleton class; you typically want it to be synchronized so you don't have the case where 2+ threads enter the method, ALL see that the "instance" is null, and then ALL create a new instance, assign it to the local member and return it.

Your threads can end up with different references to the "same" instance in that case. So you synchronize the code block, only let the first thread create the instance if it's null, and otherwise ALWAYS return the same one to all callers.

The if(instance == null) check plus the return are cheap; on the order of microseconds I believe for the future calls to getInstance (or in your example incCounter) so no need to shy away from the synchronized keyword if you need it; that's what it is for.

That being said, if you can't spare microseconds... well then you might be using the wrong language :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.