Java线程安全 - 锁定整个静态类,但仅限于一种方法

Eri*_*ric 5 java static multithreading static-methods

我实现了一个静态帮助程序类,可以帮助缓存和检索数据库中的一些只读,不可变,非易失性数据.

(剥离)示例:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

我为静态类读取它的方式,如果我将synchronized关键字添加到reloadAllCaches()方法,这将在该方法执行时对整个类应用锁.它是否正确?(编辑:是的,不正确.感谢您的回复.)

注意:我希望对getter方法的线程安全性和它们返回的对象保持不可知,因为这些数据永远不会发生变化,并希望尽快返回.

Nit*_*ram 6

如果将synchronized关键字添加到reloadAllCaches()函数,synchronized则在reloadAllCaches()函数运行时,获取该关键字的类中的所有其他静态函数都无法执行.

非静态函数如何执行,无论它们是否获得synchronized关键字都无关紧要.还synchronized可以执行没有关键字的所有其他函数.

毕竟一个功能synchronized可以看起来像:

public class Bar
{
    public static void foo()
    {
        synchronized (Bar.class)
        {
            // your code
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

synchronized可以像这样查看带有关键字的非静态函数:

public class Bar
{
    public void foo()
    {
        synchronized (this)
        {
            // your code
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,静态和非静态函数具有不同的同步上下文,并且不会使用synchronized关键字阻止彼此的执行.

对于你的情况,我建议使用a 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)