这个单例实现是线程安全的吗?

本文关键字:安全 线程 单例 实现 | 更新日期: 2023-09-27 18:18:47

我有一个数据库连接的类实现。现在,这不是一个标准的SQL数据库。

我需要知道以下是否是一个好的实现,如果不是-为什么。

我需要一个带参数的单例类,这就是我如何设计它的。

class Connection 
{
    private string param1;
    private string param2;
    private static readonly IList<Connection> connections = new List<Connection>();
    private Connection()
    {
        //Prevent instantiation
    }
    private Connection(string param1, string param2)
    {
        this.param1 = param1;
        this.param2 = param2;
    }
    public static Connection getInstance(string param1, string param2)
    { 
        foreach(Connection c in connections)
        {
            if(c.param1 = param1 && c.param2 == param2)
                return c;
        }
        Connection new_conn = new Connection(param1, param2);
        connections.Add(new_conn);
        return new_conn;
    }
}

它的用法如下:

Connection c = Connection.getInstance(abc, xyz);
Connection d = Conn

*UPDATE -现在可以了吗?*

class Connection 
{
    private string param1;
    private string param2;
    private static readonly ConcurrentDictionary<Tuple<string, string, string>, Connection> connections
        = new ConcurrentDictionary<Tuple<string, string>, Connection>();
    private Connection()
    {
        //Prevent instantiation
    }
    private Connection(string param1, string param2)
    {
        this.param1 = param1;
        this.param2 = param2;
    }
    public static Connection getInstance(string param1, string param2)
    { 
        Connection conn = activeConnections.GetOrAdd(new Tuple<string, string> 
            param1,param2), new Connection (param1, param2));
        return conn;
    }
}

这个单例实现是线程安全的吗?

不,它不是线程安全的-您在没有任何同步的情况下修改List<T>,并且List<T>不是线程安全的。

此外,如果两个调用同时进入,则可能最终得到两个具有相同参数的连接,两者都查看所有现有连接,然后都创建一个新连接。

我建议您使用ConcurrentDictionary,键为两个参数的元组。除此之外,这也会更有效率。

您需要调用GetOrAdd来获取现有连接或创建并添加一个新连接。

这甚至不会编译,因为你的集合"连接"是非静态的?

也许这样更好:

class Connection
{
    private readonly string param1;
    private readonly string param2;
    private  static readonly IList<Connection> connections = new List<Connection>();
    private Connection()
    {
        //Prevent instantiation
    }
    private Connection(string param1, string param2)
    {
        this.param1 = param1;
        this.param2 = param2;
    }
    public static Connection getInstance(string param1, string param2)
    {
        lock (connections)
        {
            var connection = connections.FirstOrDefault(c => c.param1.Equals(param1) && c.param2.Equals(param2));
            if (connection != null)
            {
                return connection;
            }
            else
            {
                var new_conn = new Connection(param1, param2);
                connections.Add(new_conn);
                return new_conn;
            } 
        }
    }
}

但是对我来说,在Connection类中保存Connection类型的List仍然有点奇怪…