现在的位置: 首页 > 综合 > 正文

乱涂C#多线程05

2018年02月07日 ⁄ 综合 ⁄ 共 5016字 ⁄ 字号 评论关闭
【文章标题】: 乱涂C#多线程05
【文章作者】: 有酒醉
【作者邮箱】: wuqr32@sina.com
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
记住,我们只能使用监督程序同步访问对象引用,而不是值类型.当Monitor.Enter接收值类型时,它首先将进行一次封箱,每一次封箱产生新的对象,这将不会导致同步访问.
 
示例 - 传递值类型 
// CValueTypeDemo.cpp
// Author by Yzl
#using < mscorlib.dll >
using namespace System;
using namespace System::Threading;

#pragma managed
__gc 
class  CValueTypeDemo
{
    
public:
        
static void ThreadProc(Object * state)
        
{
            Thread::Sleep(
500);
            Console::WriteLine(S
"Object:{0}",state->ToString());
            Object __pin 
*temp = __box(x);
            unsigned 
char *ix = (unsigned char*)temp;
            
            
try
            
{
                Monitor::Enter(temp);
                WriteMemoryContents(ix 
- 4,16);
            }

            
catch(Exception *ex)
            
{
                Console::WriteLine(ex
->ToString());    
            }

            __finally
            
{
                
//Monitor::Exit(temp);    
            }

            
        }

        
static void WriteMemoryContents(unsigned char*startAddress,int nBytes)
        
{
            
for (int i = 0; i < nBytes; i ++)
            
{
                
if (i % 8 == 0)
                    Console::Write(
"Address {0:x}:",__box((int)(startAddress) + i));
                
if (startAddress[i] < 16)
                    Console::Write(
"0");
                Console::Write(
"{0:x}",__box(startAddress[i]));    
                
if (i % 4 == 3)
                    Console::Write(
"  ");
                
if (i % 8 == 7)
                    Console::WriteLine();
                    
            }

            Console::WriteLine();    
        }

    
private:
        
static Int32 x = 5;
}
;

#pragma managed
int main()
{
    ThreadPool::QueueUserWorkItem(
new WaitCallback(0,CValueTypeDemo::ThreadProc),new String("Yzl01"));
        ThreadPool::QueueUserWorkItem(
new WaitCallback(0,CValueTypeDemo::ThreadProc),new String("Yzl02"));
        ThreadPool::QueueUserWorkItem(
new WaitCallback(0,CValueTypeDemo::ThreadProc),new String("Yzl03"));
        Console::ReadLine();
}
 
__pin 关键字防止无用单元收集器移动对象同时也可以让C++编译器允许我们将其强制转换为检查内存所需的非托管指针.
编译运行:
E:/>cl CValueTypeDemo.cpp /clr
E:/>CValueTypeDemo
Object:Yzl01
Address 4be39ac:03000000  0807b979
Address 4be39b4:05000000  00000000
Object:Yzl02
Address 4be5144:04000000  0807b979
Address 4be514c:05000000  00000000
Object:Yzl03
Address 4be62bc:03000000  0807b979
Address 4be62c4:05000000  00000000
exit
测试表明数据并未同步.第一次封箱产生的对象是4be39ac,它的同步对象索引块为03000000,值为05000000.
如果我们需要同步访问一个值类型,那么可以使用typeof(v)获取同步对象.
 
示例 -- 采用typeof同步数据
 

using System;
using System.Threading;

public class TypeofDemo
{
    
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(
"Object:{0},Current Thread:{1}",state,AppDomain.GetCurrentThreadId());
        
        
lock(typeof(int))
        
{
            x 
= AppDomain.GetCurrentThreadId();
            Console.WriteLine(
"x={0}",x);
        }

    }

    
    
private static int x = 3;
}
编译运行:
E:/>csc TypeofDemo.cs
E:/>TypeofDemo
Object:Yzl01,Current Thread:2416
x=2416
Object:Yzl02,Current Thread:2416
x=2416
Object:Yzl03,Current Thread:2404
x=2404
exit
E:/>
记住,typeof(v)对于所有的v实例总是返回相同的对象.我们测试一下:
// TypeofDemo.cs
// Author by Yzl

using System;
using System.Threading;

public class TypeofDemo
{
    
public static void Main(string[] args)
    
{
        ThreadPool.QueueUserWorkItem(
new WaitCallback(ThreadProc),1);
            ThreadPool.QueueUserWorkItem(
new WaitCallback(ThreadProc),2);
            ThreadPool.QueueUserWorkItem(
new WaitCallback(ThreadProc),3);
            Console.ReadLine();
    }


    
private static void ThreadProc(object state)
    
{
        
lock(((int)state).GetType())
        
{
            Thread.Sleep(
500);
            Console.WriteLine(
"Object:{0},Current Thread:{1}",state,AppDomain.GetCurrentThreadId());
            Thread.Sleep(
500);
            Console.WriteLine(
"Object:{0},Current Thread:{1}",state,AppDomain.GetCurrentThreadId());
        }

    }

}

运行如下:
E:/>csc TypeofDemo.cs
E:/>TypeofDemo
Object:1,Current Thread:1020
Object:1,Current Thread:1020
Object:2,Current Thread:2496
Object:2,Current Thread:2496
Object:3,Current Thread:1020
Object:3,Current Thread:1020
exit
很明显各个线程先后执行完毕.如果将lock语句改为lock(state)我们观察下又会是什么样的结果:
E:/>TypeofDemo
Object:1,Current Thread:2444
Object:1,Current Thread:2444
Object:2,Current Thread:2508
Object:3,Current Thread:2512
Object:2,Current Thread:2508
Object:3,Current Thread:2512
exit
线程执行并无顺序,2508号线程还没未执行完就被2512号线程抢去了.换句话说,这时的lock并没有起到同步对象的作用.
线程同步还涉及到死锁等现象,这里不再探讨.合理地应用锁才可能最大限度地预防数据破坏及产生死锁.
End.
--------------------------------------------------------------------------------
【版权声明】: 本文原创于厦门, 转载请注明作者并保持文章的完整, 谢谢!
                                                       2007年03月02日 13:33:38
【上篇】
【下篇】

抱歉!评论已关闭.