开发者

Thread safety for static variables

class ABC implements Runnable {
    private static int a;
    private static int b;
    public void run() {
    }
}

I have a Java class as above. I have multiple threads of this class. In the 开发者_如何转开发run() method, the variables a & b are incremented each for several times. On each increment, I am putting these variables in a Hashtable.

Hence, each thread will increment both variables and putting them in Hashtable. How can I make these operations thread safe?


I would use AtomicInteger, which is designed to be thread-safe and is dead easy to use and imparts the absolute minimal of synchronization overhead to the application:

class ABC implements Runnable {
    private static AtomicInteger a;
    private static AtomicInteger b;
    public void run() {
        // effectively a++, but no need for explicit synchronization!
        a.incrementAndGet(); 
    }
}

// In some other thread:

int i = ABC.a.intValue(); // thread-safe without explicit synchronization


Depends on what needs to be thread-safe. For these int primitives, you'll need either to replace them with AtomicInteger's or only operate with them within synchronized method or block. If you need to make your cross-thread Hashtable thread-safe, you don't need to do anything, as it already is synchronized.


Use a synchronized method, e.g.

public synchronized void increment()
{
  a++; b++;
  // push in to hash table.
}

The above is good if you are accessing the statics through a single instance, however if you have multiple instances, then you need to synchronize on some static object - something like (untested)..

private static Object lock = new Object();

in the method

public void increment()
{
  synchronize(lock)
  {
    a++;b++;
    // do stuff
  }
}

NOTE: These approaches assume that you want to increment a and b in one atomic action, the other answers highlight how they can be individually incremented using atomics.


I'd like to add some details about the answer to this question.

Firstly, the OP is asking about :

How can I make these operations thread safe?

Before answer this question, we need to reach the consistency about what is thread safe. The definition I like mostly is that from "Java Concurrency In Practice" and it's

A class is thread safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.

If you agree with the definition, it means we reach the consistency before further discussion. Let's return to the operations you meant, it's a++ and b++, after the increment, you will put them into a HashTable.

For the a++ operation, it's not really a single operation. It obeys the model of read modify write. As you can see, it actually contains three individual steps. Read the value, add one to it and save it back. If you have two threads read the variable a with value 1 at the same time, after the modifications and save back operations. The value will be 2, but it actually should be 3. To avoid this situation happen, like what others have suggested, you can use AtomicInteger instead of int type directly. The AtomicInteger will guarantee some operations like increment to execute atomically. That means, the read modify write operations can't be divided and will be executed as one individual step.
After that, the OP wants to save the value into a HashTable. The HashTable is a thread safe container, no other synchronization needed.
Hope this clarification can help someone in other way. Thanks.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜