线程同步之对象

从今天开始,学习C#以及.NET的一些基本知识,大家不要笑话。以前东一点西一点看过一些,但是语言的组织和侧重点不太符合我的学习需要,这里相当于是做一个简单的编辑和整理,供以后翻查之便,同时也可以与大家共同交流。

这里的总结一下一些线程同步常用的方法,本篇基本都是基于对象的加锁来进行线程同步的。
volatile关键字
volatile关键字算是线程同步中最简单的一个了。基本思想是,由于编译器会对数据的存取有一定的优化,例如:
int  i = 1 ;
int  a = i;

由于编译器判断在对a和i赋值期间没有其它操作,就会暂存i的值,在给a赋值时不会去真正读取i的值,而是使用暂存的i值。但是如果在多线程或者硬件编程的时候,i值是有可能在这两句话之间发生变化的,因此我们需要去读取i真实的值。

volatile   int  i = 1 ;
int  a = i;

这样就可以避免这个问题,在每次使用i值时,都会去读取i的真实值,阻止了编译器的优化。volatile只能对应用于这些类型:

  • Reference types.
  • Pointer types (in an unsafe context). Note that while the pointer itself can be volatile, the object that it points to cannot. In other words, you cannot declare a "pointer to volatile."
  • Integral types such as sbyte, byte, short, ushort, int, uint, char, float, and bool.
  • An enum type with an integral base type.
  • Generic type parameters known to be reference types.
  • and .

volatile关键字只能被用于类或者结构的数据成员,不能用于局部变量。


Interlocked类
Interlocked 类只能用于整数变量的同步,同时多用于加减操作。
Interlocked.Increment( ref  counter);  //  counter++
Interlocked.Increment( ref  counter);  //  counter--
Interlocked.Add( ref  counter,  2 );  //  counter+=2
Interlocked.Exchange( ref  counter,  2 );  //  counter=2

这些方法都是作为原子操作完成,如果在执行过程中有其他线程请求counter,都将处于等待状态,直到操作完成。

Moniter类
Moniter.Enter(object)
获得一个对象的锁,如果该对象已经被其他线程独占,则该线程阻塞直到其他线程释放对该对象的锁。

Moniter.Exit(object)
释放一个对象的锁。如果在一个线程中,多次对一个对象使用Enter(),那么也应该使用相同次数的Exit()来释放对其锁。

bool Moniter.TryEnter(object, int)
在一段时间内尝试获得某对象的锁,如果在该时间段内成功获得锁,返回true,否则返回false。如果使用无int或者TimeSpan参数的重载,则仅尝试一次。

Moniter.Wait() / Moniter.Pulse()
只有获得锁的线程能够使用Wait()。使用该方法会立刻释放该对象的锁(无论用过多少次Enter()都会执行同样次数的Exit()),然后重新等待去获得对象锁,一些重载方法指定了等待时间。如果成功获得对象锁,则返回true,否则返回false(没有指定等待时间的重载方法只能返回true,因为其只有在获得锁之后才能进行下去)。在获得对象锁之后,会立即对该对象执行之前同样次数的Enter(),进入到Wait()之前的状态。

执行Wait()之后的线程进入到wait queue内,直到获得对象锁的线程发送Pulse()指令,将wait queue的最首等待线程加入ready queue,PulseAll()指令将把wait queue里所有的等待线程加入ready queue。然后释放(Exit())对象锁之后,ready queue之内的第一个线程会获得对象锁并继续运行。如果没有执行Pulse,即没有将wait queue的线程加入ready queue,那么这些线程将一直处于等待状态不会得到运行。

lock关键字
有了Moniter类的基础,lock关键字就很简单了。

lock (x)
{
    DoSomething();
}

这段代码等价于
System.Object obj  =  (System.Object)x;
System.Threading.Monitor.Enter(obj);
try
{
    DoSomething();
}
finally
{
    System.Threading.Monitor.Exit(obj);
}

转载于:https://www.cnblogs.com/forck/archive/2008/04/16/1155802.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值