C# 读写锁

读写锁

///


/// 提供异步独占和并发执行支持
///

public sealed class AsyncReaderWriter
{
///
/// 在当前实例中保护所有共享状态的锁
///

private readonly object _lock = new object();

///


/// 并发读任务等待执行的队列
///

private readonly Queue _waitingCocurrent = new Queue();

///


/// 独占写任务等待执行的队列
///

private readonly Queue _waitingExclusive = new Queue();

///


/// 并发读任务正在执行的数量
///

private int _currentConcurrent = 0;

///


/// 独占写任务是否正在执行
///

private bool _currentlyExclusive = false;

///


/// 非泛型的任务创建工厂
///

private TaskFactory _factory;

///


/// 初始化
///

public AsyncReaderWriter()
{
this._factory = Task.Factory;
}

///


/// 使用指定的初始化, 为我们创建所有任务
///

/// 用来创建所有任务的
public AsyncReaderWriter(TaskFactory factory)
{
if (factory == null)
throw new ArgumentNullException("factory");
this._factory = factory;
}

///


/// 获取当前队列中正在等待的独占写任务数量
///

public int WaitingExclusive { get { lock (_lock) return this._waitingExclusive.Count; } }

///


/// 获取当前队列中正在等待的并发读任务数量
///

public int WaitingConcurrent { get { lock (_lock) return this._waitingCocurrent.Count; } }

///


/// 获取并发读任务正在执行的数量
///

public int CurrentConcurrent { get { lock (_lock) return this._currentConcurrent; } }

///


/// 获取当前独占写任务是否正在执行
///

public bool CurrentlyExclusive { get { lock (_lock) return this._currentlyExclusive; } }

///


/// 将独占写入队到
///

/// 将要被以独占写方式执行的
/// 表示执行提供的的任务
public Task QueueExclusiveWriter(Action action)
{
var task = new Task(state =>
{
try
{
//运行提供的action
((Action)state)();
}
finally
{
//确保我们完成后清理
FinishExclusiveWriter();
}
}, action, this._factory.CancellationToken, this._factory.CreationOptions);

lock (_lock)
{
//如果当前有任务正在运行,或者其他的独占写任务需要运行, 入队
//否则,没有其他正在运行或将要运行的任务,现在就执行当前任务
if (this._currentlyExclusive || this._currentConcurrent > 0 || this._waitingExclusive.Count > 0)
{
this._waitingExclusive.Enqueue(task);
}
else
{
RunExclusive_RequiresLock(task);
}
}
return task;
}

///


/// 将独占写入队到
///

/// 委托封装的方法的返回值类型。
/// 将要被以独占写方式指定的
/// 表示执行提供的的任务
public Task QueueExclusiveWriter(Func fun)
{
var task = new Task(state =>
{
try
{
return ((Func)state)();
}
finally
{
FinishExclusiveWriter();
}
}, fun, this._factory.CancellationToken, this._factory.CreationOptions);

lock (_lock)
{
//如果当前有任务正在运行,或者其他的独占写任务需要运行, 入队
//否则,没有其他正在运行或将要运行的任务,现在就执行当前任务
if (this._currentlyExclusive || this._currentConcurrent > 0 || this._waitingExclusive.Count > 0)
{
this._waitingExclusive.Enqueue(task);
}
else
{
RunExclusive_RequiresLock(task);
}
}
return task;
}

///


/// 将并发读入队到
///

/// 将要被以并发读方式执行的
/// 表示执行提供的的任务
public Task QueueConcurrentReader(Action action)
{
var task = new Task(state =>
{
try
{
((Action)state)();
}
finally
{
FinishConcurrentReader();
}
}, action, this._factory.CancellationToken, this._factory.CreationOptions);

lock (_lock)
{
//如果现在有独占写任务正在运行或者等待
//将当前任务入队
if (this._currentlyExclusive || this._waitingExclusive.Count > 0)
{
this._waitingCocurrent.Enqueue(task);
}
else
{
//否则立即调度
RunConcurrent_RequiresLock(task);
}
}
return task;
}

///


/// 将并发读入队到
///

/// 委托封装的方法返回值类型
/// 将要被以并发读方式执行的
/// 表示执行提供的的任务
public Task QueueConcurrentReader(Func fun)
{
var task = new Task(state =>
{
try
{
return ((Func)state)();
}
finally
{
FinishConcurrentReader();
}
}, fun, this._factory.CancellationToken, this._factory.CreationOptions);

lock (_lock)
{
if (_currentlyExclusive || this._waitingExclusive.Count > 0)
{
this._waitingCocurrent.Enqueue(task);
}
else
{
RunConcurrent_RequiresLock(task);
}
}
return task;
}

region 私有方法

///


/// 开始指定的独占任务
///

/// 即将开始的独占任务
private void RunExclusive_RequiresLock(Task exclusive)
{
this._currentlyExclusive = true;
exclusive.Start(this._factory.Scheduler ?? TaskScheduler.Current);
}

///


/// 开始指定的并发任务
///

/// 即将开始的并发任务
private void RunConcurrent_RequiresLock(Task concurrent)
{
this._currentConcurrent++;
concurrent.Start(this._factory.Scheduler ?? TaskScheduler.Current);
}

///


/// 开始并发队列中的所有任务
///

private void RunConcurrent_RequiresLock()
{
while (this._waitingCocurrent.Count > 0)
{
RunConcurrent_RequiresLock(this._waitingCocurrent.Dequeue());
}
}

///


/// 完成并发读任务
///

private void FinishConcurrentReader()
{
lock (_lock)
{
//运行到此处,表示一个并发任务已结束
this._currentConcurrent--;

//如果现在正在运行的并发任务数为0, 并且还有正在等待的独占任务, 执行一个
if (this._currentConcurrent == 0 && this._waitingExclusive.Count > 0)
{
RunExclusive_RequiresLock(this._waitingExclusive.Dequeue());
}
//否则, 如果现在没有等待的独占任务,而有一些因为某些原因等待的并发任务(它们本应该在添加到队列的时候就开始了), 运行所有正在等待的并发任务
else if (this._waitingExclusive.Count == 0 && this._waitingCocurrent.Count > 0)
{
RunConcurrent_RequiresLock();
}
}
}

///


/// 完成独占写任务
///

private void FinishExclusiveWriter()
{
lock (_lock)
{
//运行到此处,表示一个独占任务已结束
this._currentlyExclusive = false;

//如果当前仍有正在等待的独占任务, 以内联方式运行下一个
if (this._waitingExclusive.Count > 0)
{
RunExclusive_RequiresLock(this._waitingExclusive.Dequeue());
}
//否则, 如果当前仍有正在等待的并发任务, 运行所有
else if (this._waitingCocurrent.Count > 0)
{
RunConcurrent_RequiresLock();
}
}
}
#endregion
}

使用方式:

var read = new Action(() =>
{
Debug.WriteLine($"读取:{File.ReadLines(fileName).EmptyToNull()?.Last()}");
});

var write = new Action(() =>
{
var text = $"{DateTime.Now.Ticks.ToString()}\r\n";
File.AppendAllText(fileName, text);
Debug.Write($"\t写入:{text}");
});

var rw = new AsyncReaderWriter();
for(var i = 0; i < 10; i++)
{
rw.QueueExclusiveWriter(write);
rw.QueueConcurrentReader(read);
}

posted @ 2017-10-25 16:38  A_ning  阅读(3250)  评论(0)    收藏  举报