通过值类型进行Timer类的线程的同步。
2010-07-21 16:29
375 查看
timer类线程的使用时根据时间间隔,不停启动线程。他不会因为上一个线程没有运行完而不启动线程。也就是timer的定时启动线程没有任何条件限制,无论什么情况都会启动线程。
很多情况下定时启动的线程其实是希望顺序执行的,也就上一个线程没有执行完的是很下面的线程是不希望执行的。或者并不是很讲究顺序,而是只希望同一个时刻只有一个线程在运行,这个线程在运行的时候其他后启动的线程是直接不启动,或者启动了不真正执行操作。
在这个需求的背景下,产生了这个线程同步的问题。我使用之值类型的方式同步。是用一个bool类型的状态变量判断是否当前是否有线程在使用。如果有当前线程直接将线程return。在线程启动后且判断状态位为可用后,设置状态位,在线程的最后将状态变量复位。
这样的思路是正确的,而且其思路其实就是信号机制,不过信号机制在等待信号的时候是将当前线程阻断等到信号后再执行,我这边是信号表示繁忙时,立刻将当前线程return掉。
但是细细想来有几个不严谨的地方。
第一点:例如,一个线程第一句话获得判断状态位后第二句话才是设置状态位为繁忙,如果正不巧,在执行第二句话之前,另外一个线程也启动了,恰巧也执行了执行了第一句话也就通过了状态判断,程序就会出现2个线程同时执行而产生线程同步问题。其实这个问题很少会发生因为timer类线程是顺序启动的,启动间隔足够执行一个值类型的操作。但是,这个情况往往会在线程调试特别中断在判断设置状态位为繁忙这一句上。想想是不是呢。
第二点:正常情况下,线程的具体操作我们都会用try执行进行容错,为了防止中间意外的退出,我们会在finally里加上重置的语句。这里需要切忌一点,线程开头判断状态位进行return操作的语句不能放在try中,要么会因为finally里的语句而造成状态位失效了。
第二点很好解决,只要放在线程的开头,因为值类型的操作也不会产生什么错误。
第一点的解决就要稍微繁琐一点。其实原理也很简单,用lock这类同步方式,在进行判断与设置两步操作上lock一下,或者用其他信号机制已保证判断与设置状态时只能有一个线程在操作。比较郁闷的是值类型是不能被lock的(因为值类型的操作是不会产生同步问题的)所以还得设置一个objec用来lock变量,呵呵。
其实还有一个小问题,比如线程如果里面有什么报错,或者其他什么在调试时候人为原因而造成finally里的重置状态位未执行,可以在监控窗口里监控状态位变量,在发生这个问题的时候手动在监控窗口里复位一下值。
下面列出代码的模板
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
很多情况下定时启动的线程其实是希望顺序执行的,也就上一个线程没有执行完的是很下面的线程是不希望执行的。或者并不是很讲究顺序,而是只希望同一个时刻只有一个线程在运行,这个线程在运行的时候其他后启动的线程是直接不启动,或者启动了不真正执行操作。
在这个需求的背景下,产生了这个线程同步的问题。我使用之值类型的方式同步。是用一个bool类型的状态变量判断是否当前是否有线程在使用。如果有当前线程直接将线程return。在线程启动后且判断状态位为可用后,设置状态位,在线程的最后将状态变量复位。
这样的思路是正确的,而且其思路其实就是信号机制,不过信号机制在等待信号的时候是将当前线程阻断等到信号后再执行,我这边是信号表示繁忙时,立刻将当前线程return掉。
但是细细想来有几个不严谨的地方。
第一点:例如,一个线程第一句话获得判断状态位后第二句话才是设置状态位为繁忙,如果正不巧,在执行第二句话之前,另外一个线程也启动了,恰巧也执行了执行了第一句话也就通过了状态判断,程序就会出现2个线程同时执行而产生线程同步问题。其实这个问题很少会发生因为timer类线程是顺序启动的,启动间隔足够执行一个值类型的操作。但是,这个情况往往会在线程调试特别中断在判断设置状态位为繁忙这一句上。想想是不是呢。
第二点:正常情况下,线程的具体操作我们都会用try执行进行容错,为了防止中间意外的退出,我们会在finally里加上重置的语句。这里需要切忌一点,线程开头判断状态位进行return操作的语句不能放在try中,要么会因为finally里的语句而造成状态位失效了。
第二点很好解决,只要放在线程的开头,因为值类型的操作也不会产生什么错误。
第一点的解决就要稍微繁琐一点。其实原理也很简单,用lock这类同步方式,在进行判断与设置两步操作上lock一下,或者用其他信号机制已保证判断与设置状态时只能有一个线程在操作。比较郁闷的是值类型是不能被lock的(因为值类型的操作是不会产生同步问题的)所以还得设置一个objec用来lock变量,呵呵。
其实还有一个小问题,比如线程如果里面有什么报错,或者其他什么在调试时候人为原因而造成finally里的重置状态位未执行,可以在监控窗口里监控状态位变量,在发生这个问题的时候手动在监控窗口里复位一下值。
下面列出代码的模板
private bool isRunning;
private object syncRot=new object();
private void timerThreadFunction(object status)
{
lock(this.syncRot)
{
//判断状态位及设置状态位操作
if(this.sRunning) return;
this.isRunning=true;
}
try
{
//线程具体操作
}
catch
{
//容错操作
}
finally
{
//复位操作
this.isRunning=false;
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
相关文章推荐
- 通过 Object.prototype.toString.call() 进行类型判断
- 定义一个不受计算机字长限制的整数类INT,要求INT与INT以及INT与C++基本数据类型int之间能进行+、-、×、÷和=运算,并且能通过cout输出INT类型的值。(持续添加)
- 信号量进行同步(linux POSIX的实时扩展,用于线程)!
- java线程同步时,不同线程通过不同方法,访问同一资源
- Domino9下通过定时代理—使多台domino 服务器进行数据库复制(同步)
- 【UNIX】通过线程的同步和互斥完成的AB循环
- 为了在线程间进行可靠的通信,也为了互斥访问,同步是必要的。
- Linux下通过共享内存进行进程间通信,进程间同步使用信号量来实现
- 黑客通过网页或电子邮件进行攻击的主要类型
- 使用信号量进行线程间同步
- 【菜鸟C++学习笔记】27.通过operator关键字进行类型转换
- 通过网络NTP协议进行时间同步
- 使用POSIX Threads进行多线程编程(二) ——使用互斥量同步线程
- Android四大组件之Service 远程服务 通过AIDL进行进程间复杂类型数据交换
- 线程间无需特别的手段进行通信,因为线程间可以共享数据结构,也就是一个全局变量可以被两个线程同时使用,不过要注意的是线程间需要做好同步。
- java的UUID类型字段,如何通过jdbc进行数据库的CRUD
- compass 整合hibernate spring 的第二种方式 ( 通过 定时器进行数据同步)compass-2.2.0 lucene-2.9.2. hibernate-distribut spring 2.5.6 paoding
- Unity3D中通过UNET对多个物体进行同步
- 单核单处理器的环境下对多线程进行同步的常用方法
- 如何:对制造者线程和使用者线程进行同步(C# 编程指南)的详细注释