本文介绍3种线程安全模式
1,lock
2,Mutex
3,MethodImpl
以前写的一个MYSQL数据库连接池ConnectionPool.CS
using System; using System.Collections.Generic; using System.Linq; using System.Text;using System.IO; using System.Threading; using MySql.Data.MySqlClient; using System.Runtime.CompilerServices; namespace queue.service.basic {public class ConnectionPool{private Stack<MySqlConnection> pool;private const int POOL_MAX_SIZE = 20;private int current_Size = 0;private string ConnString = "";//连接字符串 private SysProperty sysProperty;private const string SYS_PROPERTY = "config\\SysProperty.xml";private static ConnectionPool connPool;private ConnectionPool(){if (pool == null){pool = new Stack<MySqlConnection>();}}[MethodImpl(MethodImplOptions.Synchronized)]public static ConnectionPool getInstance(){if (connPool == null){connPool = new ConnectionPool();}return connPool;}public MySqlConnection getConnection(){MySqlConnection conn;lock (this){if (pool.Count == 0){if (current_Size < POOL_MAX_SIZE){conn = createConnection();current_Size++;//把conn加入到pool 中 pool.Push(conn);}else{try{Monitor.Wait(this);}catch (Exception e){Console.WriteLine(e.Message);}}}conn = (MySqlConnection)pool.Pop();}return conn;}private string GetConnString(){if (ConnString == ""){sysProperty = new SysProperty().LoadProperty(Path.Combine(SYS_PROPERTY));string ip = sysProperty.getPropertyValue("databaseIP");string dbName = sysProperty.getPropertyValue("databaseName");string userID = sysProperty.getPropertyValue("databaseUser");string userPwd = sysProperty.getPropertyValue("databasePassword"); ConnString = "Database=" + dbName +";Data Source=" + ip +";User Id=" + userID +";Password=" + userPwd + ";" +"pooling=true;CharSet=utf8;port=3306;";}return ConnString;}public void releaseConnection(MySqlConnection conn){lock (this){pool.Push(conn);Monitor.Pulse(this);}}private MySqlConnection createConnection(){lock (this){MySqlConnection newConn = new MySqlConnection(GetConnString());newConn.Open();return newConn;}}} }
总结:
1,上面类中使用了 主要使用了 lock 方式。
lock()是对一个对象加互斥锁,只允许一个线程访问其后大括号中语句块,直到该语句块的代码执行完才解锁,解锁后才允许其他的线程执行其语句块。
2,单例模式使用了懒汉模式。
饿汉式是在类装载的时候直接得到该类的实例,可以说是前期绑定的;懒汉式是后期绑定的,类加载的时候connPool是空的,在需要的时候才被创建且仅创建一次。饿汉式的速度快,效率高,但是耗费系统资源;懒汉式则相反。懒汉式还存在一个问题,就是后期绑定不能确保对象只能被实例化一次,这需要对指示类是否实例化的标志设置1个互斥锁,仅允许1个线程访问。这样就可以确保对象只被实例化一次。
3,单例模式的线程安全使用了 MethodImpl。
他指定了getInstance()方法同时只能被一个线程使用。
4,使用Mutex类进行同步
修改代码为:
private static Mutex mutex = new Mutex();public static ConnectionPool getInstance(){mutex.WaitOne();if (connPool == null){connPool = new ConnectionPool();}mutex.ReleaseMutex();return connPool;}