怪不得以前做这个:
void XXX(Guid guid)
{
lock(guid.ToString())
{
//....
}
}
都觉得根本没有把那段代码作为临界段处理。原来lock只认引用。不任任何对象的比较方法的。。于是我自己做了一个支持所有类型的HashCodeLock
只要对象是纯意义上相等的。那么在哪里进行锁定都是作为临界处理。使用方法就是
using(new HashCodeLock( obj ))
{
}
或
using(new HashCodeLock( obj , msTimeout ))
{
}
有msTimeout的重载版本中。如果超时那么将抛出异常
using System;
using System.Collections;
using System.Reflection;
using System.Threading;
using System.Diagnostics;using LostinetSample;namespace LostinetSample
{
public class HashCodeLockTimeoutException:Exception
{
public HashCodeLockTimeoutException(string msg):base(msg){}
} /// <res>
/// <code>
/// using(new LostinetSample.HashCodeLock(111))
/// {
/// //now this thread is synchronized for int 111
/// }
/// </code>
/// </res>
public class HashCodeLock:IDisposable
{
class Allocator
{
class Node
{
int typecode;
int hashcode;
public Node(object obj)
{
typecode=obj.GetType().GetHashCode();
hashcode=obj.GetHashCode();
}
override public bool Equals(object obj)
{
if(obj == null)
return false;
if(obj is Node)
{
Node n=(Node)obj;
return n.typecode==typecode&&n.hashcode==hashcode;
}
return false;
}
override public int GetHashCode()
{
return typecode+hashcode;
}
} static ArrayList al=new ArrayList();
static public object Alloc(object obj)
{
Node n=new Node(obj);
lock(al.SyncRoot)
{
int index=al.IndexOf(n);
if(index!=-1)
{
n=(Node)al[index];
}
al.Add(n);
return n;
}
}
static public object Release(object obj)
{
Node n=new Node(obj);
lock(al.SyncRoot)
{
int index=al.IndexOf(n);
if(index==-1)
throw(new Exception("cant release obj:node not found"));
n=(Node)al[index];
return n;
}
}
}
public HashCodeLock(object obj)
{
Init(obj,Timeout.Infinite);
}
public HashCodeLock(object obj,int msTimeout)
{
Init(obj,msTimeout);
}
public HashCodeLock(object obj,TimeSpan tsTimeout)
{
Init(obj,(int)tsTimeout.Milliseconds);
}
void Init(object obj,int ms)
{
if(obj==null)throw(new ArgumentNullException("obj"));
MethodBase mb=new StackTrace(2).GetFrame(0).GetMethod();
m=mb.ReflectedType.FullName+":"+mb.ToString();
if(!Monitor.TryEnter(Allocator.Alloc(obj),ms))
{
Allocator.Release(obj);
throw(new HashCodeLockTimeoutException("lock timeout"));
}
o=obj;
released=false;
} bool released=true;
object o;
string m; void IDisposable.Dispose()
{
if(released)
throw(new Exception("lock at "+m+" already released!"));
released=true;
Monitor.Exit(Allocator.Release(o));
}
~HashCodeLock()
{
if(!released)
throw(new Exception("lock at "+m+" have not released!"));
}
}
}namespace ConsoleApplication1
{
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
t=new Thread(new ThreadStart(WaitForReady));
t.Start(); for(int i=0;i<10;i++)
new Thread(new ThreadStart(
new Job(i).Start
))
.Start(); Console.WriteLine("Start!");
isReady=true;
}
static bool isReady=false;
static void WaitForReady()
{
while(!isReady)
Thread.Sleep(100);
}
static Thread t; class Job
{
int i;
public Job(int index)
{
i=index;
}
public void Start()
{
t.Join();
int ms=3000;
if(i==5)
ms=300; if(i==8)
{
new HashCodeLock( int.Parse("11") );
GC.Collect();
} try
{
//lock(11.ToString())
using(new HashCodeLock( int.Parse("11") , ms ))
{
Thread.Sleep(100);
W("job:"+i+" ok");
Thread.Sleep(100);
}
}
catch(Exception x)
{
W("job:"+i+" - "+x.GetType().FullName+":"+x.Message);
}
}
static public void W(string str)
{
Console.WriteLine(str);
}
}
}
}
void XXX(Guid guid)
{
lock(guid.ToString())
{
//....
}
}
都觉得根本没有把那段代码作为临界段处理。原来lock只认引用。不任任何对象的比较方法的。。于是我自己做了一个支持所有类型的HashCodeLock
只要对象是纯意义上相等的。那么在哪里进行锁定都是作为临界处理。使用方法就是
using(new HashCodeLock( obj ))
{
}
或
using(new HashCodeLock( obj , msTimeout ))
{
}
有msTimeout的重载版本中。如果超时那么将抛出异常
using System;
using System.Collections;
using System.Reflection;
using System.Threading;
using System.Diagnostics;using LostinetSample;namespace LostinetSample
{
public class HashCodeLockTimeoutException:Exception
{
public HashCodeLockTimeoutException(string msg):base(msg){}
} /// <res>
/// <code>
/// using(new LostinetSample.HashCodeLock(111))
/// {
/// //now this thread is synchronized for int 111
/// }
/// </code>
/// </res>
public class HashCodeLock:IDisposable
{
class Allocator
{
class Node
{
int typecode;
int hashcode;
public Node(object obj)
{
typecode=obj.GetType().GetHashCode();
hashcode=obj.GetHashCode();
}
override public bool Equals(object obj)
{
if(obj == null)
return false;
if(obj is Node)
{
Node n=(Node)obj;
return n.typecode==typecode&&n.hashcode==hashcode;
}
return false;
}
override public int GetHashCode()
{
return typecode+hashcode;
}
} static ArrayList al=new ArrayList();
static public object Alloc(object obj)
{
Node n=new Node(obj);
lock(al.SyncRoot)
{
int index=al.IndexOf(n);
if(index!=-1)
{
n=(Node)al[index];
}
al.Add(n);
return n;
}
}
static public object Release(object obj)
{
Node n=new Node(obj);
lock(al.SyncRoot)
{
int index=al.IndexOf(n);
if(index==-1)
throw(new Exception("cant release obj:node not found"));
n=(Node)al[index];
return n;
}
}
}
public HashCodeLock(object obj)
{
Init(obj,Timeout.Infinite);
}
public HashCodeLock(object obj,int msTimeout)
{
Init(obj,msTimeout);
}
public HashCodeLock(object obj,TimeSpan tsTimeout)
{
Init(obj,(int)tsTimeout.Milliseconds);
}
void Init(object obj,int ms)
{
if(obj==null)throw(new ArgumentNullException("obj"));
MethodBase mb=new StackTrace(2).GetFrame(0).GetMethod();
m=mb.ReflectedType.FullName+":"+mb.ToString();
if(!Monitor.TryEnter(Allocator.Alloc(obj),ms))
{
Allocator.Release(obj);
throw(new HashCodeLockTimeoutException("lock timeout"));
}
o=obj;
released=false;
} bool released=true;
object o;
string m; void IDisposable.Dispose()
{
if(released)
throw(new Exception("lock at "+m+" already released!"));
released=true;
Monitor.Exit(Allocator.Release(o));
}
~HashCodeLock()
{
if(!released)
throw(new Exception("lock at "+m+" have not released!"));
}
}
}namespace ConsoleApplication1
{
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
t=new Thread(new ThreadStart(WaitForReady));
t.Start(); for(int i=0;i<10;i++)
new Thread(new ThreadStart(
new Job(i).Start
))
.Start(); Console.WriteLine("Start!");
isReady=true;
}
static bool isReady=false;
static void WaitForReady()
{
while(!isReady)
Thread.Sleep(100);
}
static Thread t; class Job
{
int i;
public Job(int index)
{
i=index;
}
public void Start()
{
t.Join();
int ms=3000;
if(i==5)
ms=300; if(i==8)
{
new HashCodeLock( int.Parse("11") );
GC.Collect();
} try
{
//lock(11.ToString())
using(new HashCodeLock( int.Parse("11") , ms ))
{
Thread.Sleep(100);
W("job:"+i+" ok");
Thread.Sleep(100);
}
}
catch(Exception x)
{
W("job:"+i+" - "+x.GetType().FullName+":"+x.Message);
}
}
static public void W(string str)
{
Console.WriteLine(str);
}
}
}
}
return hashcode ^ typecode;
((object) obj).Equals(obj2)
那么就是说 Node n=new Node(obj);
lock(al.SyncRoot)
{
int index=al.IndexOf(n);
if(index!=-1)这里的index就会永远都会是-1,因为每一个Node都是新的,跟你Node里面装的是什么没有什么关系。而我觉得ArrayList.Contains(obj)用的是
obj.Equals(obj2)
也就是Node.Equals(obj2)才对,这样的话只要new Node(obj)里面的obj,的typecode和hashcode都一样的话就会一样。如果这种说法对的话,那么我还是觉得用hashcode^typecode要好一点。
using System.Collections;
using System.Reflection;
using System.Threading;
using System.Diagnostics;using LostinetSample;namespace LostinetSample
{
public class HashCodeLockTimeoutException:Exception
{
public HashCodeLockTimeoutException(string msg):base(msg){}
} /// <res>
/// <code>
/// using(new LostinetSample.HashCodeLock(111))
/// {
/// //now this thread is synchronized for int 111
/// }
/// </code>
/// </res>
public class HashCodeLock:IDisposable
{
class Allocator
{
class Node
{
int typecode;
int hashcode;
public Node(object obj)
{
typecode=obj.GetType().GetHashCode();
hashcode=obj.GetHashCode();
}
override public bool Equals(object obj)
{
if(obj == null)
return false;
if(obj is Node)
{
Node n=(Node)obj;
return n.typecode==typecode&&n.hashcode==hashcode;
}
return false;
}
override public int GetHashCode()
{
return typecode+hashcode;
}
} static ArrayList al=new ArrayList();
static public object Alloc(object obj)
{
object n=new Node(obj);
lock(al.SyncRoot)
{
int index=al.IndexOf(n);
if(index!=-1)
{
n=al[index];
}
al.Add(n);
return n;
}
}
static public object Release(object obj)
{
object n=new Node(obj);
lock(al.SyncRoot)
{
int index=al.IndexOf(n);
if(index==-1)
throw(new Exception("cant release obj:node not found"));
n=al[index];
al.RemoveAt(index);
return n;
}
}
}
public HashCodeLock(object obj)
{
Init(obj,Timeout.Infinite);
}
public HashCodeLock(object obj,int msTimeout)
{
Init(obj,msTimeout);
}
public HashCodeLock(object obj,TimeSpan tsTimeout)
{
Init(obj,(int)tsTimeout.Milliseconds);
}
void Init(object obj,int ms)
{
if(obj==null)throw(new ArgumentNullException("obj"));
MethodBase mb=new StackTrace(2).GetFrame(0).GetMethod();
m=mb.ReflectedType.FullName+":"+mb.ToString();
if(!Monitor.TryEnter(Allocator.Alloc(obj),ms))
{
Allocator.Release(obj);
throw(new HashCodeLockTimeoutException("lock timeout"));
}
o=obj;
released=false;
} bool released=true;
object o;
string m; void IDisposable.Dispose()
{
if(released)
throw(new Exception("lock at "+m+" already released!"));
released=true;
Monitor.Exit(Allocator.Release(o));
}
~HashCodeLock()
{
if(!released)
throw(new Exception("lock at "+m+" have not released!"));
}
}
}namespace ConsoleApplication1
{
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
t=new Thread(new ThreadStart(WaitForReady));
t.Start(); for(int i=0;i<10;i++)
new Thread(new ThreadStart(
new Job(i).Start
))
.Start(); Console.WriteLine("Start!");
isReady=true;
}
static bool isReady=false;
static void WaitForReady()
{
while(!isReady)
Thread.Sleep(100);
}
static Thread t; class Job
{
int i;
public Job(int index)
{
i=index;
}
public void Start()
{
t.Join();
int ms=3000;
if(i==5)
ms=300; //index5任务超时 if(i==8)
{
//错误的用法!..
new HashCodeLock( int.Parse("11") );
GC.Collect();
} try
{
//lock(11.ToString())
using(new HashCodeLock( int.Parse("11") , ms ))
{
Thread.Sleep(100);
W("job:"+i+" ok");
Thread.Sleep(100);
}
}
catch(Exception x)
{
W("job:"+i+" - "+x.GetType().FullName+":"+x.Message);
}
}
static public void W(string str)
{
Console.WriteLine(str);
}
}
}
}