1

对于非高性能锁定......只是健壮的线程安全代码......我想要简单的lock (obj) { code; },但我想在它之前和之后记录(这样我可以通过获取来自用户的日志),我想支持 ReaderWriterLocks。(是的,我意识到 Monitor 和 SpinLock 等更快......但这不是高性能的高线程数......速度在这里不是问题。)

我已经看到了通过 执行此操作的建议using (new ReadLock(myLock)) { code; },但是经常怀疑新类的编码。

Sooo,这就是我想出的。我对你们所有人的问题:(1)当我在评论中指出使用以下代码时,有什么问题吗?(2) 关于如何改进此代码以使其更可靠、更简单或更高效的任何建议?

请注意,TccLog 只是我们自己的 log4net 包装器......但它可以是您选择的任何日志库。

// Locks.cs == structs intended to be used with using statements for reliable, easy-to-code, logged locks
using System;
using System.Threading;
namespace Tcc.Common
{
/// <summary>
/// A ReadLock allows any number of readers but prevents any writers until the ReadLock is disposed.
/// ReadLocks do NOT log as they can't cause deadlocks without some other thread having a WriteLock.
/// Use a ReadLock with the following syntax:
/// 
/// using (new ReadLock(someReaderWriterLock, timeoutInMS))
/// { code; }
/// 
/// which is equivalent to:
/// 
/// someReaderWriterLock.AcquireReaderLock(timeoutInMS);
/// try
/// { code; }
/// finally
/// { someReaderWriterLock.ReleaseReaderLock(); }
/// </summary>
public struct ReadLock : IDisposable
{
    ReaderWriterLock TheLock;

    public ReadLock(ReaderWriterLock theLock)
    {
        TheLock = theLock;
        TheLock.AcquireReaderLock(100000);
    }

    public ReadLock(ReaderWriterLock theLock, int timeoutMS)
    {
        TheLock = theLock;
        TheLock.AcquireReaderLock(timeoutMS);
    }

    public void Dispose()
    {
        TheLock.ReleaseReaderLock();
    }
}


/// <summary>
/// A WriteLock allows only that one writer and no readers.
/// WriteLocks will log when they start waiting for the lock and again when they release the lock.
/// You may want to log.TraceLock("LOCKED") in the first line of your code that you have acquired the lock.
/// Use a WriteLock with the following syntax:
/// 
/// using (new WriteLock(someReaderWriterLock, timeoutInMS))
/// { code; }
/// 
/// which is equivalent to:
/// 
/// LOG.TraceLock("LOCKING");
/// someReaderWriterLock.AcquireWriterLock(timeoutInMS);
/// try
/// { code; }
/// finally
/// { someReaderWriterLock.ReleaseWriterLock(); LOG.TraceLock("UNLOCKED"); }
/// </summary>
public struct WriteLock : IDisposable
{
    private static TccLog LOG = new TccLog(2);

    ReaderWriterLock TheLock;

    public WriteLock(ReaderWriterLock theLock)
    {
        TheLock = theLock;
        LOG.TraceLock("LOCKING");
        TheLock.AcquireWriterLock(100000);
    }

    public WriteLock(ReaderWriterLock theLock, int timeoutMS)
    {
        TheLock = theLock;
        LOG.TraceLock("LOCKING");
        TheLock.AcquireWriterLock(timeoutMS);
    }

    public void Dispose()
    {
        TheLock.ReleaseWriterLock();
        LOG.TraceLock("UNLOCKED");
    }
}


/// <summary>
/// A FullLock is like the built-in 'lock' (Monitor on any heap object), except it implements logging.
/// FullLocks will log when they start waiting for the lock and again when they release the lock.
/// You may want to log.TraceLock("LOCKED") in the first line of your code that you have acquired the lock.
/// Use a FullLock with the following syntax:
/// 
/// using (new FullLock(someHeapObject))
/// { code; }
/// 
/// which is equivalent to:
/// 
/// LOG.TraceLock("LOCKING");
/// lock (someHeapObject)
/// { code; }
/// LOG.TraceLock("UNLOCKED");
/// </summary>
public struct FullLock : IDisposable
{
    private static TccLog LOG = new TccLog(2);

    object TheLock;

    public FullLock(object theLock)
    {
        TheLock = theLock;
        LOG.TraceLock("LOCKING");
        Monitor.Enter(TheLock);
    }

    public void Dispose()
    {
        Monitor.Exit(TheLock);
        LOG.TraceLock("UNLOCKED");
    }
}


/// <summary>
/// A NamedLock is like the built-in 'lock' (Monitor on any heap object), except it implements logging.
/// NamedLocks will log when they start waiting for the lock and again when they release the lock.
/// You may want to log.TraceLock("LOCKED") in the first line of your code that you have acquired the lock.
/// Use a NamedLock with the following syntax:
/// 
/// using (new NamedLock(someHeapObject, "name"))
/// { code; }
/// 
/// which is equivalent to:
/// 
/// LOG.TraceLock("LOCKING name");
/// lock (someHeapObject)
/// { code; }
/// LOG.TraceLock("UNLOCKED name");
/// </summary>
public struct NamedLock : IDisposable
{
    private static TccLog LOG = new TccLog(2);

    object TheLock;
    string Name;

    public NamedLock(object theLock, string name)
    {
        Name = name;
        TheLock = theLock;
        LOG.TraceLock("LOCKING " + name);
        Monitor.Enter(TheLock);
    }

    public void Dispose()
    {
        Monitor.Exit(TheLock);
        LOG.TraceLock("UNLOCKED " + Name);
    }
}
4

0 回答 0