设为首页 收藏本站
查看: 1079|回复: 0

[经验分享] SQLite多线程写锁文件解决方案

[复制链接]

尚未签到

发表于 2016-12-1 06:03:12 | 显示全部楼层 |阅读模式
  在sqlite编程中多线程同时写时会出现异常,我写了个类来解决这个问题。
  思路很简单,就是在开始写操作时,记下写操作的托管线程id,表示目前有线程正在做写操作;其他线程来写时,需要先检测是否有进程正在做写操作,如果有就需要等待,等待到某一个配置的超时时间时,会抛出异常终止等待;如果没有则直接放行,此线程可以获得写锁。最后写操作执行完毕时需要释放锁。
  下面是具体的代码:
<!---->/// <summary>
/// 用于在多线程访问sqlite时防止同步写导致锁文件
/// 
/// 使用方法:
/// using (SQLiteWriteLock sqliteLock = new SQLiteWriteLock(SQLite链接字符串))
/// {
///     //sqlite 写操作代码
/// }
/// 
/// 可以通过在配置文件appSettings节中添加设置 SQLiteWriteLockTimeout 的value值控制锁等待的超时时间,该值必须为正整数数字,单位为毫秒,
/// 默认的超时时间是1000ms
/// </summary>
public sealed class SQLiteWriteLock : IDisposable
{
    
#region 静态字段和属性
    
const short WAIT_TIME = 5;
    
static readonly object locker = new object();
    
static Dictionary<stringint> _dbThreadIdDict = new Dictionary<stringint>();

    
/// <summary>
    
/// 获得写操作的超时时间,单位为毫秒,可以通过配置文件appSettings节中添加设置 SQLiteWriteLockTimeout 的value值控制锁等待的超时时间,该值必须为正整数数字,单位为毫秒
    
/// 默认的超时时间是1000ms
    
/// </summary>
    public static int SQLiteWriteLockTimeout
    {
        
get
        {
            
string configValule = ConfigurationManager.AppSettings["SQLiteWriteLockTimeout"];
            
if (!string.IsNullOrEmpty(configValule))
            {
                
return int.Parse(configValule);
            }
            
return 1000;
        }
    }
    
#endregion

    
private readonly string _connString;

    
//隐藏无参构造函数
    private SQLiteWriteLock() { }

    
public SQLiteWriteLock(string connString)
    {
        _connString 
= connString;
        AcquireWriteLock();
    }

    
#region 私有方法

    
private void AcquireWriteLock()
    {
        
int threadId = Thread.CurrentThread.ManagedThreadId;

        
int waitTimes = 0;
        
while (_dbThreadIdDict.ContainsKey(_connString) && _dbThreadIdDict[_connString] != threadId)
        {
            Thread.Sleep(WAIT_TIME);
            waitTimes 
+= WAIT_TIME;
#if DEBUG
            Console.WriteLine(_connString 
+ " wait for " + waitTimes + " ms");
#endif
            
if (waitTimes > SQLiteWriteLockTimeout)
            {
                
throw new TimeoutException("SQLite等待写操作超时");
            }
        }

        
lock (locker)
        {
            
if (!_dbThreadIdDict.ContainsKey(_connString))
                _dbThreadIdDict.Add(_connString, threadId);
        }
    }

    
private void ReleaseWriteLock()
    {
        
lock (locker)
        {
            
if (_dbThreadIdDict.ContainsKey(_connString))
            {
                _dbThreadIdDict.Remove(_connString);
            }
        }
    }

    
#endregion

    
#region IDisposable 成员

    
public void Dispose()
    {
        ReleaseWriteLock();
    }

    
#endregion
}

  希望此文有用。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-307766-1-1.html 上篇帖子: SQLite嵌入式数据库中的王者 下篇帖子: SQLite入门与分析(二)---设计与概念
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表