zoukankan      html  css  js  c++  java
  • 多线程同步技术(一)

    多线程编程过程中,难免会涉及到资源共享的问题,在并发的线程中,如果不对线程加以控制,线程抢夺共享资源,对资源的读取和修改混乱,结果会导致不是我们想要的结果,这就需要引入线程同步的技术。

    先演示下没有同步技术的案例:

    class ThreadTT
        {
            int counter = 0;
            public void LockTest()
            {
                Thread t1 = new Thread(new ParameterizedThreadStart(Run));
                Thread t2 = new Thread(new ParameterizedThreadStart(Run));
                Thread t3 = new Thread(new ParameterizedThreadStart(Run));
    
                t1.Start("t1");
                t2.Start("t2");
                t3.Start("t3");
            }
            public void Run(object id)
            {
                    for (int i = 0; i < 100; i++)
                    {
                        counter++;
                        Thread.Sleep(100);
                        counter--;
                        Console.WriteLine("{0} counter {1}", id, counter);
                    }
            }
        }

    当执行LockTest() 方法之后,打印出的counter的值则是错乱的:

    image

    下面开始引入同步技术:

    1.LOCK

    class ThreadTT
        {
            int counter = 0;
            public void LockTest()
            {
                Thread t1 = new Thread(new ParameterizedThreadStart(Run));
                Thread t2 = new Thread(new ParameterizedThreadStart(Run));
                Thread t3 = new Thread(new ParameterizedThreadStart(Run));
    
                t1.Start("t1");
                t2.Start("t2");
                t3.Start("t3");
            }
            private  object obj = new object();
            public void Run(object id)
            {
                lock (obj)
                {
                    for (int i = 0; i < 100; i++)
                    {
                        counter++;
                        Thread.Sleep(100);
                        counter--;
                        Console.WriteLine("{0} counter {1}", id, counter);
                    }
                }
            }
        }

    再运行LockTest :

    image

    现在counter每次都只有一个线程占用;

    2.Monitor

    class ThreadTT
        {
            int counter = 0;
            public void LockTest()
            {
                Thread t1 = new Thread(new ParameterizedThreadStart(Run));
                Thread t2 = new Thread(new ParameterizedThreadStart(Run));
                Thread t3 = new Thread(new ParameterizedThreadStart(Run));
    
                t1.Start("t1");
                t2.Start("t2");
                t3.Start("t3");
            }
            private static  object obj = new object();
            public void Run(object id)
            {
                Monitor.Enter(obj);
                    for (int i = 0; i < 10; i++)
                    {
                        counter++;
                        Thread.Sleep(100);
                        counter--;
                        
                        Console.WriteLine("{0} counter {1}", id, counter);
                    }
               Monitor.Exit(obj);
            }
        }

    Monitor.Wait() 释放线程锁,并阻塞线程,直到重新获取锁,否则之后的代码不再执行;

    Monitor .pulse() 通知正在准备的线程,可以获取线程锁;

    static void Main()
            {
                object obj = new object();
                Thread t1 = new Thread(()=> {
                    Monitor.Enter(obj);
                    Console.WriteLine("t1 enter");
                    Console.WriteLine("t1.dosomething");
    
                    Monitor.Wait(obj);
                    Thread.Sleep(2000);
                    Console.WriteLine("t1 重新获取锁obj");
                    Monitor.Pulse(obj);
                    Monitor.Exit(obj);
                    Console.WriteLine("t1 exit");
                });
    
                Thread t2 = new Thread(()=> {
                    Monitor.Enter(obj);
                    
                    Console.WriteLine("t2 enter");
                    Monitor.Pulse(obj);
                    Console.WriteLine("t2 puslse");
    
                    Monitor.Wait(obj);
                    Console.WriteLine("t2 重新获取obj");
                    Monitor.Exit(obj);
                    Console.WriteLine("t2 exit");
                });
    
                t1.Start();
                t2.Start();
    
                Console.Read();
            }

    image

    程序执行,首先进入t1,执行到Monitor.Wait(obj); 线程t1释放锁,并阻塞,开始进入线程t2,执行到Monitor.Wait(obj),线程t2阻塞,线程t1重新获取锁  执行到结束,并释放信号,t2接收到信号,继续执行结束

    Monitor.Wait(obj,3000);

    当前线程阻塞,等待3s钟,如果没有获取到锁,则继续执行下去

    3.Mutex互斥锁

    Mutex对象是一个同步基元,可以用来做线程间的同步。

    若多个线程需要共享一个资源,可以在这些线程中使用Mutex同步基元。当某一个线程占用Mutex对象时,其他也需要占用Mutex的线程将处于挂起状态,Mutex 通常处于空闲状态,线程在使用的时候通过waitone()来获取一个可用的互斥,如果有,则获取互斥权限,执行线程,如果没有,则阻塞在那里直到等到信号;

    private static Mutex mut = new Mutex();
            private const int numIterations = 1;
            private const int numThreads = 3;
            static void Main()
            {
                for (int i = 0; i < numThreads; i++)
                {
                    Thread newThread = new Thread(new ThreadStart(ThreadProc));
                    newThread.Name = String.Format("Thread{0}", i + 1);
                    newThread.Start();
                }
    
                Console.Read();
            }
    
            private static void ThreadProc()
            {
                for (int i = 0; i < numIterations; i++)
                {
                    UseResource();
                }
            }
    
            // This method represents a resource that must be synchronized
            // so that only one thread at a time can enter.
            private static void UseResource()
            {
                // Wait until it is safe to enter.
                Console.WriteLine("{0} is requesting the mutex",
                                  Thread.CurrentThread.Name);
                mut.WaitOne();
    
                Console.WriteLine("{0} has entered the protected area",
                                  Thread.CurrentThread.Name);
    
                // Place code to access non-reentrant resources here.
    
                // Simulate some work.
                Thread.Sleep(500);
    
                Console.WriteLine("{0} is leaving the protected area",
                    Thread.CurrentThread.Name);
    
                // Release the Mutex.
               mut.ReleaseMutex();
                Console.WriteLine("{0} has released the mutex",
                    Thread.CurrentThread.Name);
            }

    image

    这里可以很清楚的看到,mutex每次只被一个线程占用,只有释放之后,另外的线程才可以进入;

  • 相关阅读:
    Windows Azure Storage (17) Azure Storage读取访问地域冗余(Read Access – Geo Redundant Storage, RA-GRS)
    SQL Azure (15) SQL Azure 新的规格
    Azure China (5) 管理Azure China Powershell
    Azure China (4) 管理Azure China Storage Account
    Azure China (3) 使用Visual Studio 2013证书发布Cloud Service至Azure China
    Azure China (2) Azure China管理界面初探
    Azure China (1) Azure公有云落地中国
    SQL Azure (14) 将云端SQL Azure中的数据库备份到本地SQL Server
    [New Portal]Windows Azure Virtual Machine (23) 使用Storage Space,提高Virtual Machine磁盘的IOPS
    Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())的注意点
  • 原文地址:https://www.cnblogs.com/yeshuimaowei/p/7458772.html
Copyright © 2011-2022 走看看