Skip to content

Instantly share code, notes, and snippets.

@emanonwzy
Forked from JeffreyZhao/gist:8630308
Created January 27, 2014 08:58
Show Gist options
  • Save emanonwzy/8645219 to your computer and use it in GitHub Desktop.
Save emanonwzy/8645219 to your computer and use it in GitHub Desktop.
///////////////////////////////////////////////////////
// Talk is cheap. Show me the code. - Linus Torvalds
///////////////////////////////////////////////////////
public abstract class CalculatorBase : IDisposable {
protected void StartCore() {
// ...
}
protected void DisposeCore() {
// ...
}
public abstract void Start();
public abstract void Dispose();
}
// 需求:编写一个计算器,继承上面的CalculatorBase类,并实现Start和Dispose方法。
// Start用于启动该计算器,Dispose则用于销毁,而启动和销毁的具体实现已经由基类
// 的StartCore与DisposeCore提供,直接调用即可,确保成功,不会抛出一场。不过问
// 题在于,Start和Dispose方法可能会被并发地执行,顺序不定,次数不定,但它们的
// 实现必须满足:
// 1. StartCore和DisposeCore都是相对较为耗时的操作,且最多只能被调用一次。
// 2. StartCore和DisposeCore一旦开始执行,则无法终止,只能执行成功。
// 3. StartCore和DisposeCore必须顺序地执行,不可有任何并行。
// 5. 假如调用Dispose时StartCore已经执行,则必须调用DisposeCore,否则不用。
// 6. 调用Dispose意味着要销毁对象,对象销毁以后的任何访问,都不会执行任何操作。
// 7. Start及Dispose方法可立即返回,不必等待StartCore或DisposeCore完成。不过,
// 8. 计算器本身不发起任何多线程或异步操作,一切都在Start和Dispose方法里完成。
// 参考实现:一个最简单的实现方法便是用锁来保护Start和Dispose方法:
public class BigLockCalculator : CalculatorBase {
private readonly object _gate = new object();
private enum Status {
NotStarted,
Started,
Disposed
}
private Status _status = Status.NotStarted;
public override void Start() {
lock (_gate) {
if (_status == Status.NotStarted) {
StartCore();
_status = Status.Started;
}
}
}
public override void Dispose() {
lock (_gate) {
if (_status == Status.Started) {
DisposeCore();
}
_status = Status.Disposed;
}
}
}
// 不过这种方法的坏处也是显而易见的,假设有许多线程同时调用Start和Dispose方法,
// 而某个Start线程稍早,则所有人都必须等待其调用完毕才能进行下一步判断。同理,假如
// Start后进入的是个Dispose线程,则又要进行再一轮等待。
// 那么,怎样可以做地更好呢?
///////////////////////////////////////////////////////
// Talk is cheap. Show me the code. - Linus Torvalds
///////////////////////////////////////////////////////
// 解答再此,但建议不要直接看答案,先自己想明白了再说,否则就失去意义了。
// https://gist.github.com/JeffreyZhao/8644613
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment