【文章标题】: 乱涂C#多线程04
【文章作者】: 有酒醉
【作者邮箱】: wuqr32@sina.com
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
三、同步变量访问
数据同步容易造成数据的破坏.虽然说数据同步可能会破坏我们的程序,但是它不会破坏类型安全性.这是因为装载诸如指针等基本类型总是基本操作,所以不会破坏托管指针和对象引用.
【文章作者】: 有酒醉
【作者邮箱】: wuqr32@sina.com
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
三、同步变量访问
数据同步容易造成数据的破坏.虽然说数据同步可能会破坏我们的程序,但是它不会破坏类型安全性.这是因为装载诸如指针等基本类型总是基本操作,所以不会破坏托管指针和对象引用.
lock 语句用于获取某个给定对象的互斥锁,执行一个语句,然后释放该锁.我们先研究下lock的内部实现方式
//
LockDemo.cs
// Author by Yzl
using System;
using System.Threading;
public class LockDemo
... {
public static void Main(string[] args)
...{
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),"Yzl01");
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),"Yzl02");
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),"Yzl03");
Console.ReadLine();
}
private static void ThreadProc(object state)
...{
Thread.Sleep(500);
Console.WriteLine("Current Object:"+state);
lock(x.GetType())
...{
x = System.AppDomain.GetCurrentThreadId();
Console.WriteLine("x="+x);
}
}
private static int x ;
}
// Author by Yzl
using System;
using System.Threading;
public class LockDemo
... {
public static void Main(string[] args)
...{
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),"Yzl01");
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),"Yzl02");
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),"Yzl03");
Console.ReadLine();
}
private static void ThreadProc(object state)
...{
Thread.Sleep(500);
Console.WriteLine("Current Object:"+state);
lock(x.GetType())
...{
x = System.AppDomain.GetCurrentThreadId();
Console.WriteLine("x="+x);
}
}
private static int x ;
}
编译运行:
E:/>csc LockDemo.cs
E:/>csc LockDemo.cs
E:/>LockDemo
Current Object:Yzl01
x=2212
Current Object:Yzl02
x=2212
Current Object:Yzl03
x=2444
exit
Current Object:Yzl01
x=2212
Current Object:Yzl02
x=2212
Current Object:Yzl03
x=2444
exit
反汇编查看内部结构:
IL_001a: ldsfld int32 LockDemo::x
IL_001f: box [mscorlib]System.Int32
IL_0024: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0029: dup
IL_002a: stloc. 0
IL_002b: call void [mscorlib]System.Threading.Monitor::Enter( object )
. try
... {
IL_0030: call int32 [mscorlib]System.AppDomain::GetCurrentThreadId()
IL_0035: stsfld int32 LockDemo::x
IL_003a: ldstr "x="
IL_003f: ldsfld int32 LockDemo::x
IL_0044: box [mscorlib]System.Int32
IL_0049: call string [mscorlib]System.String::Concat(object, object)
IL_004e: call void [mscorlib]System.Console::WriteLine(string)
IL_0053: leave.s IL_005c
} // end .try
finally
... {
IL_0055: ldloc.0
IL_0056: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_005b: endfinally
} // end handler
IL_001f: box [mscorlib]System.Int32
IL_0024: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0029: dup
IL_002a: stloc. 0
IL_002b: call void [mscorlib]System.Threading.Monitor::Enter( object )
. try
... {
IL_0030: call int32 [mscorlib]System.AppDomain::GetCurrentThreadId()
IL_0035: stsfld int32 LockDemo::x
IL_003a: ldstr "x="
IL_003f: ldsfld int32 LockDemo::x
IL_0044: box [mscorlib]System.Int32
IL_0049: call string [mscorlib]System.String::Concat(object, object)
IL_004e: call void [mscorlib]System.Console::WriteLine(string)
IL_0053: leave.s IL_005c
} // end .try
finally
... {
IL_0055: ldloc.0
IL_0056: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_005b: endfinally
} // end handler
我们很容易观察出lock实际上是应用了Monitor来进行同步变量的访问.同时也注意到了Monitor::Exit(object)放在finally中保证了同步锁的释放.
C++中没有等效于C# lock 语句,如果用C++编写代码,那么需要显式调用Monitor方法.
示例 -- C++ 中应用lock
//
CLockDemo.cpp
// Author by Yzl
# using < mscorlib.dll >
using namespace System;
using namespace System::Threading;
#pragma managed
__gc class CLockDemo
... {
public:
static void ThreadProc(Object* state)
...{
Thread::Sleep(1000);
Console::WriteLine(S"Current Object:{0}",state->ToString());
Object *iObj = __box(x);
Type *iType = iObj->GetType();
try
...{
//Lock the x
Monitor::Enter(iType);
x = AppDomain::GetCurrentThreadId();
Console::WriteLine(S"x={0}",x.ToString());
}
catch(Exception *ex)
...{
Console::WriteLine(ex->ToString());
}
__finally
...{
Monitor::Exit(iType);
}
}
private:
static int x;
} ;
#pragma managed
int main( void )
... {
ThreadPool::QueueUserWorkItem(new WaitCallback(0,CLockDemo::ThreadProc),new String("Yzl01"));
ThreadPool::QueueUserWorkItem(new WaitCallback(0,CLockDemo::ThreadProc),new String("Yzl02"));
ThreadPool::QueueUserWorkItem(new WaitCallback(0,CLockDemo::ThreadProc),new String("Yzl03"));
Console::ReadLine();
}
// Author by Yzl
# using < mscorlib.dll >
using namespace System;
using namespace System::Threading;
#pragma managed
__gc class CLockDemo
... {
public:
static void ThreadProc(Object* state)
...{
Thread::Sleep(1000);
Console::WriteLine(S"Current Object:{0}",state->ToString());
Object *iObj = __box(x);
Type *iType = iObj->GetType();
try
...{
//Lock the x
Monitor::Enter(iType);
x = AppDomain::GetCurrentThreadId();
Console::WriteLine(S"x={0}",x.ToString());
}
catch(Exception *ex)
...{
Console::WriteLine(ex->ToString());
}
__finally
...{
Monitor::Exit(iType);
}
}
private:
static int x;
} ;
#pragma managed
int main( void )
... {
ThreadPool::QueueUserWorkItem(new WaitCallback(0,CLockDemo::ThreadProc),new String("Yzl01"));
ThreadPool::QueueUserWorkItem(new WaitCallback(0,CLockDemo::ThreadProc),new String("Yzl02"));
ThreadPool::QueueUserWorkItem(new WaitCallback(0,CLockDemo::ThreadProc),new String("Yzl03"));
Console::ReadLine();
}
编译运行:
E:/>cl ClockDemo.cpp /clr
E:/>cl ClockDemo.cpp /clr
E:/>CLockDemo
Current Object:Yzl01
x=2644
Current Object:Yzl02
x=2660
Current Object:Yzl03
x=2644
exit
Current Object:Yzl01
x=2644
Current Object:Yzl02
x=2660
Current Object:Yzl03
x=2644
exit
我们将Monitor::Exit(iType)注释掉,观察一下会有什么结果:
E:/>cl ClockDemo.cpp /clr
E:/>cl ClockDemo.cpp /clr
E:/>ClockDemo
Current Object:Yzl01
x=2672
Current Object:Yzl02
Current Object:Yzl03
x=2672
Current Object:Yzl01
x=2672
Current Object:Yzl02
Current Object:Yzl03
x=2672
到这里程序无法运行下去,停滞不前.这是由于2672号线程并未释放对象锁所造成的.同时我们也发现Object:Yzl01,Object:Yzl03采用了同一线程池中的线程运行自己的任务.
<续>
--------------------------------------------------------------------------------
【版权声明】: 本文原创于厦门, 转载请注明作者并保持文章的完整, 谢谢!
【版权声明】: 本文原创于厦门, 转载请注明作者并保持文章的完整, 谢谢!
2007年03月01日 14:10:15