日期:2014-05-17  浏览次数:21024 次

C# 多线程执行过程探讨
上代码说明问题
C# code

    class Program
    {
        static Thread t1 = new Thread(new ThreadStart(Run1));
        static Thread t2 = new Thread(new ThreadStart(Run2));
        static NetworkStream ns = null;
        static byte[] data1 = new byte[99999];
        static byte[] data2 = new byte[99999];

        static void Main(string[] args)
        {
            for (int i = 0; i < data1.Length; i++)
            {
                data1[i] = 1;
            }
            TcpClient client = new TcpClient("127.0.0.1", 8855);
            ns = client.GetStream();
            t1.Start();
            t2.Start();
        }

        static void Run1()
        {
            int i=100;//无意义
            ns.Write(data1, 0, data1.Length);
        }
        static void Run2()
        {
            int i=1000;//无意义
            ns.Write(data2, 0, data2.Length);
        }
    }


大家有看到,Run1方法和Run2方法是在t1线程和t2线程中执行的
而且这2个线程是操作的同一个NetworkStream
我的问题是按照多线程的效果,Run1和Run2同时开始执行了。
他可能是执行Run1里面的int i=100。然后执行完了后就跳到Run2里面去执行Run2里面的int i=1000
当然也可能不跳,继续执行下面的一行代码,具体实际是怎样,得看cpu调度了。
我自己的代码,我知道我都写了哪些行代码,在交替执行的时候可能会执行哪些代码我都知道。
这一切都在我的掌控之中。
但是ns.Write这个方法不是我写的,是.Net Framework里面的方法,它的内部有哪些代码我也不知道。
我担心的是,在线程中调用.Net Framework里面类的方法的时候,这些方法内部肯定不止1行代码
所以这些方法内部的代码会不会也在交替着执行呢?
不知道我表述的问题有没有表述清楚,大家有没有理解。
我再换一个方式来阐述这个问题:
大家有看到我的ns.Write方法是分别往同一个网络流里面写字节数组。
data1字节数组里面包含的全部都是1,而data2字节数组里面包含的全部都是0.
Run1方法是在往字节流西面写入1
Run2方法是在往字节流里面写入0
这2个方法操作的是同一个网络流,并且同时在运行
因此,最终的结果这个网络流里面的数据是一下哪2种情况:
A:1111111.....111110000000......000000 
B:0000000.....000001111111......111111
C:101110001110111110101010000111000011
如果是A或者B这2种情况的话,我就感觉线程是以我写的代码为准
一行代码完全执行完毕后才有可能跳入到其他线程中去执行代码
如果是C这种情况,就说明不是我写的代码也有可能会交替执行,而且它内部怎么交替我就不知道。
如果真是这样的情况,用多线程,我感觉好危险,必须要锁。

我有做过测试,我又写了一个程序,来读这个网络流,发现读出来的结果是A和B其中的1个,没有出现C的情况。
但是我也仅仅是测试了十几次,虽然没有出现C这种情况,我觉得有可能是我运气好,CPU调度的太完美。
所以发个帖子,征求大家的结论,希望能有个结果
拜求各位高人指点迷津。

------解决方案--------------------
没有仔细看你后边一大堆问题,仅看了一下前边的代码(如果代码写的比一大堆啰嗦的注释清晰,那就好!):

ns.Write不会产生冲突,它是线程安全的,通讯的另一端可以保证连续收到data1然后是data2,或者连续收到data2然后收到data1,不会将数据打乱。
------解决方案--------------------
这个问题无非就是 write 方法是否线程安全的问题.
和本身 多线程 的探讨应该还扯不上什么关系.

并且由于socket 提供了异步BeginSend. 所以对 write 和 send 进行多线程操作也显得没有意义.

如果你要用多线程, 我觉得就 socket类型 而言的程序上, 应该用在 resv 之后的 消息处理过程上. 也就是你的业务逻辑上.

只要你的业务逻辑才是 更多需要考虑多线程的地方. socket 本身完全有一套异步解决方案