线程之间同步

来源:互联网 发布:月入10万的网络女主播 编辑:程序博客网 时间:2024/06/05 20:37

 线程之间同步(主要结合前人的文章,加上自己的理解,整理而成,希望对你有用..)

 

//想明白了就好了.....

 

1  Mutex的WaitOne()函数

 

class Program
{
    
static void Main(string[] args)
    {
        
// 为截图方便把窗体设小一点
        Console.WindowWidth = 30; Console.BufferWidth = 30
        Console.WindowHeight 
= 16; Console.BufferHeight = 16;
        
        Mutex mk 
= new Mutex(false"my mutex");
        
for (int i = 0; i < 1000; i++)
        {
            mk.WaitOne();
            
for (int j = 0; j < 30; j++)
            {
                Console.Write(
">");
                Thread.Sleep(
100);
            }
            mk.ReleaseMutex();
            Thread.Sleep(
500);
        }
    }
}

接连运行此程序的两个实例,把它们并排排放在一起(如下图所示),即可看到箭头从左边的窗体“穿越”到右边窗体的效果了。Mutex和Monitor的概念十分相似,只不过Monitor是.net内建的线程同步机制,Mutex是封装了Windows操作系统的线程同步机制;Monitor速度快,Mutex的速度要比Monitor慢很多;Monitor只能用于同步同一进程内的线程;Mutex则可以用于同步隶属于不同进程的线程。

2: 

   Mutex的WaitAll()函数

 

class Program
{
    
static void Main(string[] args)
    {
        
// 为截图方便把窗体设小一点
        Console.WindowWidth = 30; Console.BufferWidth = 30
        Console.WindowHeight 
= 16; Console.BufferHeight = 16;
        
        Mutex mk1 
= new Mutex(false"my mutex1");
        Mutex mk2 
= new Mutex(false"my mutex2");
        Mutex[] mks 
= new Mutex[] { mk1, mk2 };

        
for (int i = 0; i < 1000; i++)
        {
            Mutex.WaitAll(mks);
            
for (int j = 0; j < 30; j++)
            {
                Console.Write(
">");
                Thread.Sleep(
100);
            }

            mk1.ReleaseMutex();
            mk2.ReleaseMutex();
            Thread.Sleep(
500);
        }
    }
}


3:

 

Mutex的WaitAny()函数:


class Program
 2 {
 3     static void Main(string[] args)
 4     {
 5         // 为截图方便把窗体设小一点
 6         Console.WindowWidth = 30; Console.BufferWidth = 30
 7         Console.WindowHeight = 16; Console.BufferHeight = 16;
 8         
 9         Mutex mk1 = new Mutex(false"my mutex1");
10         Mutex mk2 = new Mutex(false"my mutex2");
11         Mutex[] mks = new Mutex[] { mk1, mk2 };
12 
13         for (int i = 0; i < 1000; i++)
14         {
15             int index = Mutex.WaitAny(mks); // 返回值为此进程占用的mk在mks里的index
16             Console.Write("Index: " + index.ToString());
17             for (int j = 0; j < 30; j++)
18             {
19                 Console.Write(">");
20                 Thread.Sleep(100);
21             }
22 
23             mks[index].ReleaseMutex();
24             Thread.Sleep(new Random().Next(1003000));
25         }
26     }
27 }
如果同时运行此程序的两个实例,正如本文摘要里所写的,只要mk1和mk2有一个是空闲的,进程就可以进去办事,所以两个进程可以同时输出">"字符。注意程序的第24行,每个进程在输出30个">"字符后都会随机Sleep 100到3000毫秒,这样就有可能出现mk1和mk2同时空闲的情况,所以就会出现一会儿进程1占用mk1而进程2占用mk2;一会儿进程1占用mk2而进程2占用mk1的情况(在下图分别用绿色和红色波浪线标出)。


4:

    EventWaitHandle 类
 

using System;
using System.Threading;

public class Example
{
    // The EventWaitHandle used to demonstrate the difference
    // between AutoReset and ManualReset synchronization events.
    //
    private static EventWaitHandle ewh;

    // A counter to make sure all threads are started and
    // blocked before any are released. A Long is used to show
    // the use of the 64-bit Interlocked methods.
    //
    private static long threadCount = 0;

    // An AutoReset event that allows the main thread to block
    // until an exiting thread has decremented the count.
    //
    private static EventWaitHandle clearCount =
        new EventWaitHandle(false, EventResetMode.AutoReset);

    [MTAThread]
    public static void Main()
    {
        // Create an AutoReset EventWaitHandle.
        //
        ewh = new EventWaitHandle(false, EventResetMode.AutoReset);

        // Create and start five numbered threads. Use the
        // ParameterizedThreadStart delegate, so the thread
        // number can be passed as an argument to the Start
        // method.
        for (int i = 0; i <= 4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked.
        // When multiple threads use a 64-bit value on a 32-bit
        // system, you must access the value through the
        // Interlocked class to guarantee thread safety.
        //
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Release one thread each time the user presses ENTER,
        // until all threads have been released.
        //
        while (Interlocked.Read(ref threadCount) > 0)
        {
            Console.WriteLine("Press ENTER to release a waiting thread.");
            Console.ReadLine();

            // SignalAndWait signals the EventWaitHandle, which
            // releases exactly one thread before resetting,
            // because it was created with AutoReset mode.
            // SignalAndWait then blocks on clearCount, to
            // allow the signaled thread to decrement the count
            // before looping again.
            //
            WaitHandle.SignalAndWait(ewh, clearCount);
        }
        Console.WriteLine();

        // Create a ManualReset EventWaitHandle.
        //
        ewh = new EventWaitHandle(false, EventResetMode.ManualReset);

        // Create and start five more numbered threads.
        //
        for(int i=0; i<=4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked.
        //
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Because the EventWaitHandle was created with
        // ManualReset mode, signaling it releases all the
        // waiting threads.
        //
        Console.WriteLine("Press ENTER to release the waiting threads.");
        Console.ReadLine();
        ewh.Set();

    }

    public static void ThreadProc(object data)
    {
        int index = (int) data;

        Console.WriteLine("Thread {0} blocks.", data);
        // Increment the count of blocked threads.
        Interlocked.Increment(ref threadCount);

        // Wait on the EventWaitHandle.
        ewh.WaitOne();

        Console.WriteLine("Thread {0} exits.", data);
        // Decrement the count of blocked threads.
        Interlocked.Decrement(ref threadCount);

        // After signaling ewh, the main thread blocks on
        // clearCount until the signaled thread has
        // decremented the count. Signal it now.
        //
        clearCount.Set();
    }
}