静态变量是否是线程安全的?C#

Rya*_*n S 42 .net c# asp.net

我想创建一个存储DataTables的类,这将阻止我的应用程序每次要检索它时导入详细信息列表.因此,这应该做一次,我相信下面的代码这样做,但我不确定它是否是线程安全的.

下面的代码位于我的三层应用程序的Business Layer部分,它将DataTable返回到表示层.

public class BusinessLayerHandler
{
    public static DataTable unitTable;
    public static DataTable currencyTable;

    public static DataTable GetUnitList()
    {
        //import lists each time the application is run
        unitTable = null;
        if (unitTable == null)
        {
            return unitTable = DatabaseHandler.GetUnitList();
        }
        else
        {
            return unitTable;
        }
    }

    public static DataTable GetCurrencyList()
    {
        //import lists each time the application is run
        currencyTable = null;
        if (currencyTable == null)
        {
            return currencyTable = DatabaseHandler.GetCurrencyList();
        }
        else
        {
            return currencyTable;
        }
    }
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏,如果有更好的方法来缓存DataTable,请告诉我.

更新:

感谢您的意见,如果我理解正确,这是建议的方法:

public class BusinessLayerHandler
{
    private static DataTable unitTable;
    private static DataTable currencyTable;

    private static readonly object unitTableLock = new object();
    private static readonly object currencyTableLock = new object();

    public static DataTable GetUnitList()
    {
        //import lists each time the application is run
        //unitTable = null;

        lock (unitTableLock)
        {
            if (unitTable == null)   
            {
                return unitTable = DatabaseHandler.GetUnitList();
            }
        }
        return unitTable;
    }

    public static DataTable GetCurrencyList()
    {
        //import lists each time the application is run
        lock (currencyTableLock)
        {
            if (currencyTable == null)
            {
                return currencyTable = DatabaseHandler.GetCurrencyList();
            }
        }
        return currencyTable;
    }
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*rth 34

看起来好像你想要做的只是加载一次并保持对它的引用.您需要保护的只是初始化变量(如果它为空).空检查,锁定和空检查再次被称为双重检查锁定,并将很好地为您服务.最佳做法是提供单独的锁定对象,以便您可以很好地控制锁的粒度.

请注意,这并不能阻止人们改变其中的值DataTable,只会阻止人们同时尝试初始化静态成员.

private static readonly object UnitTableLock = new object();
private static DataTable unitTable;
private static bool _ready = false;

public static DataTable GetUnitList()
{
    if (!_ready)
    {
        lock (UnitTableLock)
        {
            if (!_ready)
            {
                unitTable = new DataTable; //... etc
                System.Threading.Thread.MemoryBarrier();
                _ready = true;
            }
        }
    }

    return unitTable;
}
Run Code Online (Sandbox Code Playgroud)

只读取GetUnitList永不写入的结果.

参考http://en.wikipedia.org/wiki/Double-checked_locking修改


Llo*_*ell 16

我认为值得补充的是,Double Check Locking已经在.net framework 4.0中实现了一个名为的类Lazy.因此,如果您希望您的类默认包含锁定,那么您可以像这样使用它:

public class MySingleton
{
    private static readonly Lazy<MySingleton> _mySingleton = new Lazy<MySingleton>(() => new MySingleton());

    private MySingleton() { }

    public static MySingleton Instance
    {
        get
        {
            return _mySingleton.Value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Gop*_*her 8

它们不是线程安全的.你应该考虑让自己的逻辑线程安全,例如,使用lock运算符.


alu*_*lun 6

如果您使用.net 4,则可以在数据表上使用ThreadLocal包装器