且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-11-24 13:35:36

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

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

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

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

    返回unitTable;
}
 

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

修订参照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