zoukankan      html  css  js  c++  java
  • C# 语言的多线程编程,完全是本科OS里的知识

     基本知识,无参数Thread和带参数的Thread

    Thread类的参数就是参数指针,可以传入一个无参的函数。

    如果要传入带参数的函数,先new一个ParameterizedThreadStart委托实例,带参数的函数名作为它的参数。带参数的函数必须且只能有一个object参数。参考下面的

    ConterWithParam(object param)

    static int iCnt = 0;
            static readonly int N = 10000;
    
            static void Main(string[] args)
            {
                Thread[] thrs = new Thread[N];
                for (int i = 0; i < N; i++)
                {
                    thrs[i] = new Thread(Counter);
                    thrs[i].Start();               
                }
                for (int i = 0; i < N; i++)
                {              
                    thrs[i].Join();
                }
                Console.WriteLine(iCnt);
    
                iCnt = 0;
    
                ParameterizedThreadStart[] thrsp = new ParameterizedThreadStart[N];
                object param = 2;
                for (int i = 0; i < N; i++)
                {
                    thrsp[i] = new ParameterizedThreadStart(ConterWithParam);
                    thrs[i] = new Thread(thrsp[i]);
                    thrs[i].Start(param);
                }
                for (int i = 0; i < N; i++)
                {
                    //当NewThread调用Join方法的时候,MainThread就被停止执行,直到NewThread线程执行完毕
                    thrs[i].Join();
                }
                Console.WriteLine(iCnt);
            }
    
            static void Counter()
            {
                Thread.Sleep(100);
                iCnt++;
                //Console.WriteLine("finish iCnt++,now iCnt is " + iCnt);            
            }
    
            static void ConterWithParam(object param)
            {
                Thread.Sleep(100);
                int i = (int)param;
                iCnt += i;
                //Console.WriteLine("finish iCnt+"+i+",now iCnt is " + iCnt);     
            }

    该例子输出结果

    2)互斥信号灯mutex

    第一节的结果是不是有点奇怪。明明加了10000次,结果却是9550.

    带参数的那个例子,一次加2,加10000次,应该是20000才对。结果却是19678.

    这是因为对全局变量的访问iCnt出现了冲突。比如两个线程同时取到了iCnt=0时的值,同时执行了i++,那么iCnt的最后状态肯定是1,而不是会2。为了让iCnt得到正确的值。

    我们引入互斥信号灯。

    static int iCnt = 0;
            static readonly int N = 10000;
            static Mutex mut = new Mutex();
    
            static void Main(string[] args)
            {
                Thread[] thrs = new Thread[N];
                for (int i = 0; i < N; i++)
                {
                    thrs[i] = new Thread(Counter);
                    thrs[i].Start();               
                }
                for (int i = 0; i < N; i++)
                {              
                    thrs[i].Join();
                }
                Console.WriteLine(iCnt);
    
                iCnt = 0;
    
                ParameterizedThreadStart[] thrsp = new ParameterizedThreadStart[N];
                object param = 2;
                for (int i = 0; i < N; i++)
                {
                    thrsp[i] = new ParameterizedThreadStart(ConterWithParam);
                    thrs[i] = new Thread(thrsp[i]);
                    thrs[i].Start(param);
                }
                for (int i = 0; i < N; i++)
                {
                    //当NewThread调用Join方法的时候,MainThread就被停止执行,直到NewThread线程执行完毕
                    thrs[i].Join();
                }
                Console.WriteLine(iCnt);
            }
    
            static void Counter()
            {
                Thread.Sleep(10);
                //
                mut.WaitOne();            
                iCnt++;
                //释放
                mut.ReleaseMutex();
                //Console.WriteLine("finish iCnt++,now iCnt is " + iCnt);            
            }
    
            static void ConterWithParam(object param)
            {
                Thread.Sleep(10);
                //锁住
                mut.WaitOne();            
                int i = (int)param;
                iCnt += i;
                //释放
                mut.ReleaseMutex();
                //Console.WriteLine("finish iCnt+"+i+",now iCnt is " + iCnt);     
            }

    本次执行结果

    3) 同步信号灯Semaphore

    用最经典的生产者-消费者来解释。

    static Semaphore sem = new Semaphore(0, 1);
            static Semaphore sem2 = new Semaphore(0, 5);
    
            static void Main(string[] args)
            {
                Console.WriteLine("消费者等生产者生产一个item");
                Thread thConsumer = new Thread(Consume);
                thConsumer.Start();
                Thread thProductor = new Thread(Product);
                thProductor.Start();
    
                thConsumer.Join();
                thProductor.Join();
                Console.WriteLine(".............................");
    
                Console.WriteLine("多并发的例子.....");
                for (int i = 0; i < 10; i++)
                {
                    Thread t1 = new Thread(Consume2);
                    t1.Start();
                    Thread t2 = new Thread(Product2);
                    t2.Start();
                }//end for
                
    
            }
    
    
            static void Product()
            {
                Thread.Sleep(2000);
                Console.WriteLine("Product an item...");
                sem.Release();
            }
    
            static void Consume()
            {
                Thread.Sleep(1000);
                Console.WriteLine("Consumer is waiting an item...");
                sem.WaitOne();
                Console.WriteLine("Consumer get an item...");
            }
    
    
    
            static void Product2()
            {
                Thread.Sleep(1000);
                Console.WriteLine("Product an item...");
                sem2.Release();
            }
    
            static void Consume2()
            {
                Thread.Sleep(1000);
                Console.WriteLine("Consumer is waiting an item...");
                sem2.WaitOne();
                Console.WriteLine("Consumer get an item...");
            }

  • 相关阅读:
    写在彻底转向有道云笔记一个月之后
    KMP算法实现
    有道云笔记 V.S. 为知笔记
    卸载印象笔记,跟印象笔记说拜拜
    ExpandRegion for Sublime Text:快速选择文本
    Linux cat命令详解
    Vim安装插件
    Vim与正则表达式
    还没供暖
    在Linux命令行中设置并使用代理服务器
  • 原文地址:https://www.cnblogs.com/eecs/p/4018284.html
Copyright © 2011-2022 走看看