在研究双重检查锁定时,我看到了许多人建议跳过第一次检查并立即获取锁,在获取锁后再进行检查。
这让我想知道,当没有竞争时,lock (this.padlock)
是否“便宜”?
在研究双重检查锁定时,我看到了许多人建议跳过第一次检查并立即获取锁,在获取锁后再进行检查。
这让我想知道,当没有竞争时,lock (this.padlock)
是否“便宜”?
我们可以对它进行测试...
我得到:
1000000000; 2164 (no lock)
1000000000; 23258 (lock)
21.094ns per lock
代码:
using System;
using System.Diagnostics;
static class P
{
static void Main()
{
Test(1); // for JIT
Test(1000000);
}
static readonly object syncLock = new object();
static void Test(int count)
{
int j = 0;
var watch = Stopwatch.StartNew();
for(int i = 0 ; i < count ; i++)
{
for (int z = 0; z < 1000; z++)
j++;
}
watch.Stop();
long withoutMillis = watch.ElapsedMilliseconds;
Console.WriteLine("{0}; {1} (no lock)", j, watch.ElapsedMilliseconds);
j = 0;
watch = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
for (int z = 0; z < 1000; z++ )
lock (syncLock)
{
j++;
}
}
watch.Stop();
long withMillis = watch.ElapsedMilliseconds;
Console.WriteLine("{0}; {1} (lock)", j, watch.ElapsedMilliseconds);
long deltaNano = (withMillis - withoutMillis) * 1000000;
// nano = 1000 micro = 1000000 milli
double perLockNano = deltaNano/(1000.0 * count);
Console.WriteLine("{0}ns per lock", perLockNano);
}
}
ldsfld
(lock(staticLockObject)
)пјҢиҖҢдёҚжҳҜldarg0 + ldfld
(lock(this.instanceLockObject)
) - дҪ еә”иҜҘиғҪеӨҹи°ғж•ҙжөӢиҜ•д»Ҙе…Ғи®ёиҝҷж ·еҒҡгҖӮ - Marc Gravell我写这篇文章非常快,没有测试过,只是为了传达一个条件锁定的一种方法,使用扩展方法和委托或Lambda函数。我也不能肯定这是否会自我破坏,这是有可能的。
我有一些代码在多线程进程和使用协作纤维模式线程模型的进程中运行(例如,存在多个永远不会异步执行的线程)。在协作纤维模式应用程序中,锁定是无意义和浪费的,因此这可能是避免在每个必须进行锁定的点上进行大量混乱逻辑的解决方案。
// Conditional Locking concept code
namespace SystemExtensions {
public static class LockMeUp
{
private static bool isLockingEnabled = true;
// If set to true, locking will be performed
// by the extension methods below.
internal static bool LockingEnabled
{
get
{
return isLockingEnabled;
}
set
{
isLockingEnbaled = value;
}
}
static void CheckNull<TLock>( TLock target ) where TLock: class
{
if( target == null )
throw new ArgumentNullException("target cannot be null");
}
// Invoke the supplied action on the supplied lock object
public static void TryLock<TLock>(
this TLock target,
Action<TLock> action ) where TLock: class
{
CheckNull( target );
if( isLockingEnabled )
{
lock( target )
{
action( target );
}
}
else
{
action( target );
}
}
// Invoke the supplied function on the supplied
// lock object and return result:
public static T TryLock<TLock, T>(
this TLock target,
Func<TLock, T> func ) where TLock: class
{
CheckNull( target );
if( isLockingEnabled )
{
lock( target )
{
return func( target );
}
}
else
{
return func( target );
}
}
// Invoke the supplied function on the supplied lock object
// and another supplied argument, and return the result:
public static T TryLock<TLock, TArg, T>(
this TLock target,
Func<TLock, TArg, T> func,
TArg arg ) where TLock: class
{
CheckNull( target );
if( isLockingEnabled )
{
lock( target )
{
return func( target, arg );
}
}
else
{
return func( target, arg );
}
}
// Invoke the supplied action on the supplied lock object
// and another supplied argument:
public static void TryLock<TLock, TArg>(
this TLock target,
Action<TLock, TArg> func,
TArg arg ) where TLock: class
{
CheckNull( target );
if( isLockingEnabled )
{
lock( target )
{
func( target, arg );
}
}
else
{
func( target, arg );
}
}
}
///// Example:
public static class SharedList<T>
{
private static List<T> items = new List<T>();
public static bool Remove( T item )
{
return items.TryLock( (list, item) => list.Remove( item ), item );
}
public static T GetItemAt( int index )
{
return items.TryLock( (list, i) => list[i], index );
}
public static bool Contains( T item )
{
return items.TryLock( (list, it) => list.Contains( it ), item );
}
public static void Add( T item )
{
items.TryLock( (list, item) => list.Add( item ) );
}
}
} // namespace