Java Thread Security - Blocking an entire static class, but only for one method

I have a Static helper class that helps to cache and retrieve some immutable, non-time-varying data from the database from the database.

(Stripped) Example:

public class CacheHelper
{
    private static HashMap foos, bars;

    public static Foo getFoo(int fooId) { /* etc etc */ }
    public static Bar getBar(int barId) { /* etc etc */ }

    public static void reloadAllCaches()
    {
        //This is where I need it to lock access to all the other static methods
    }
}

As I read it for static classes. If I add a keyword synchronizedto the reloadAllCaches () method, this will apply the lock for the entire class while this method is executing. It's right? (Edit: Yes, not right. Thanks for the answers.)

Note. I would like to remain an agnostic for the safety of method flows getterand returned objects, since this data is never mutated and would like it to return as quickly as possible.

+5
5

synchronized reloadAllCaches(), , synchronized, reloadAllCaches().

, , synchronized . synchronized.

, synchronized :

public class Bar
{
    public static void foo()
    {
        synchronized (Bar.class)
        {
            // your code
        }
    }
}

synchronized :

public class Bar
{
    public void foo()
    {
        synchronized (this)
        {
            // your code
        }
    }
}

, .

ReentrantReadWriteLock. , Write-Lock. , , , .

, , . ReentrantReadWriteLock.

, :

public class CacheHelper
{
    private static HashMap foos, bars;
    private static java.util.concurrent.locks.ReadWriteLock lock = new java.util.concurrent.locks.ReentrantReadWriteLock();

    public static Foo getFoo(int fooId)
    {
        lock.readLock().lock();
        try {
            /* etc etc */
        } finally {
            lock.readLock().unlock();
        }
    }
    public static Bar getBar(int barId)
    {
        lock.readLock().lock();
        try {
            /* etc etc */
        } finally {
            lock.readLock().unlock();
        }
    }

    public static void reloadAllCaches()
    {
        lock.writeLock().lock();
        try {
            //This is where I need it to lock access to all the other static methods
        } finally {
            lock.writeLock().unlock();
        }
    }
}
+6

, . synchronized reloadAllCaches , , , , . , , , . ConcurrentHashMap.

+2

, .

private static volatile Map foos, bars;

public static Foo getFoo(int fooId) { return foos.get(fooId); }
public static Bar getBar(int barId) { /* etc etc */ }

public static void reloadAllCaches()
{
    Map newFoo = ...
    // populate newFoo
    foos = newFoo;

    Map newBar = ...
    // populate newBar
    bars = newBar;
}

getFoo , , .


synchronized , CacheHelper.class

, ConcurrentHashMap synchronized


.

final ConcurrentMap<Key, ExpensiveObject> map =

public ExpensiveObject getOrNull(Key key) { 
     return map.get(key); 
}

public ExpensiveObject getOrCreate(Key key) {
     synchronized(map) {
         ExpensiveObject ret = map.get(key);
         if (ret == null)
              map.put(key, ret = new ExpensiveObject(key));
         return ret;
     }
}
+2

, CacheHelper (CacheHelper.class) reloadAllCaches(), , , , static, synchronized, , .

0

, - , .

, , , . .

, .

, - , reloadAllCaches , .

, / , , .

If your reuse is for reloading several cached cards (according to your example), you may find that you need to abstract the cached objects with another layer, otherwise you can exit the synchronization mode with caches as they are applied.

0
source

All Articles