是静态变量线程安全的? C# [英] Are static variables thread-safe? C#

查看:557
本文介绍了是静态变量线程安全的? C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个类,存储数据表,这将prevent我的应用我要找回它每一次导入的详细列表。因此,这应该是做一次,我认为以下code这样做,但我不知道这是否是线程安全的。

下面code是在我的三层应用程序的业务层部分,它返回一个DataTable到presentation层。

 公共类BusinessLayerHandler
{
    公共静态数据表unitTable;
    公共静态数据表currencyTable;

    公共静态数据表GetUnitList()
    {
        //导入列出每个应用程序运行时
        unitTable = NULL;
        如果(unitTable == NULL)
        {
            返回unitTable = DatabaseHandler.GetUnitList();
        }
        其他
        {
            返回unitTable;
        }
    }

    公共静态数据表GetCurrencyList()
    {
        //导入列出每个应用程序运行时
        currencyTable = NULL;
        如果(currencyTable == NULL)
        {
            返回currencyTable = DatabaseHandler.GetCurrencyList();
        }
        其他
        {
            返回currencyTable;
        }
    }
 

任何帮助是AP preciated,如果有更好的方法如何缓存数据表请让我知道。

更新:

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

 公共类BusinessLayerHandler
{
    私有静态数据表unitTable;
    私有静态数据表currencyTable;

    私人静态只读对象unitTableLock =新的对象();
    私人静态只读对象currencyTableLock =新的对象();

    公共静态数据表GetUnitList()
    {
        //导入列出每个应用程序运行时
        // unitTable = NULL;

        锁定(unitTableLock)
        {
            如果(unitTable == NULL)
            {
                返回unitTable = DatabaseHandler.GetUnitList();
            }
        }
        返回unitTable;
    }

    公共静态数据表GetCurrencyList()
    {
        //导入列出每个应用程序运行时
        锁定(currencyTableLock)
        {
            如果(currencyTable == NULL)
            {
                返回currencyTable = DatabaseHandler.GetCurrencyList();
            }
        }
        返回currencyTable;
    }
}
 

解决方案

看来好像所有你想要做的是加载一次,并保持对它的引用。所有你需要警惕正在初始化变量,如果是零。空检查,锁和空再次检查被称为双重检查锁定并会很好地帮助你。它提供一个独立的锁定对象的最佳实践,让你有很好的控制锁的粒度。

请注意这并不变异的数据表,它只停止人们试图初始化静态成员的同时,里面的值阻止人们

 私有静态只读对象UnitTableLock =新的对象();
私有静态数据表unitTable;
私有静态布尔_ready = FALSE;

公共静态数据表GetUnitList()
{
    如果(!_ready)
    {
        锁定(UnitTableLock)
        {
            如果(!_ready)
            {
                unitTable =新的DataTable; //... 等等
                System.Threading.Thread.MemoryBarrier();
                _ready = TRUE;
            }
        }
    }

    返回unitTable;
}
 

仅从 GetUnitList 的结果读从来不写吧。

修订参照<一个href="http://en.wikipedia.org/wiki/Double-checked_locking">http://en.wikipedia.org/wiki/Double-checked_locking

I want to create a class which stores DataTables, this will prevent my application to import a list of details each time I want to retrieve it. Therefore this should be done once, I believe that the following code does so, but I am not sure if it is thread-safe.

The below code is in the Business Layer Section of my three tier application, it is returning a DataTable to the Presentation Layer.

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;
        }
    }

Any help is appreciated, if there is a better way how to cache a DataTable please let me know.

Update:

Thanks to your opinions, this is the suggested method to do it, if I understood correctly:

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;
    }
}

解决方案

It appears as though all you want to do is load it once and keep a reference to it. All you need to guard is initialising the variable if it's null. Null checking, locking and null checking again is called Double Check Locking and will work well for you. It's best practice to provide a separate locking object, so you have good control over granularity of locks.

Note this doesn't stop people from mutating the value inside the DataTable it only stops people from trying to initialise the static member at the same time.

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;
}

Only read from the result of GetUnitList never write to it.

Amended with reference to http://en.wikipedia.org/wiki/Double-checked_locking

这篇关于是静态变量线程安全的? C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆