Thread safety for static variables

前端 未结 4 1469
天涯浪人
天涯浪人 2021-02-19 03:12
class ABC implements Runnable {
    private static int a;
    private static int b;
    public void run() {
    }
}

I have a Java class as above. I hav

相关标签:
4条回答
  • 2021-02-19 03:31

    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.

    0 讨论(0)
  • 2021-02-19 03:34

    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
    
    0 讨论(0)
  • 2021-02-19 03:40

    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 讨论(0)
  • 2021-02-19 03:42

    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.

    0 讨论(0)
提交回复
热议问题