• 基元线程同步构造之信号量(Semaphore)


      信号量(semaphore)不过是由内核维护的 int32变量而已,(说通俗点就是好比一个线程容器里面允许执行的线程数,0计数就是允许执行的0个线程数,1就是允许执行的1个线程数,2就是允许执行的2个线程数,等等一次类推。。。。。。,0就是当前执行的线程数占满了容器没空余的了)

        当信号量为0时,在信号量上等待的线程会全部阻塞;

        当信号量大于0时,就解除阻塞。

      在一个信号量上等待的一个线程解除阻塞时,内核自动从信号量的计数中减1,线程运行完后调用Release,计数就加1。信号量还关联了一个最大的Int32值,当前计数绝不允许超过最大计数。下面展示了semaphore类的样子: 

    
    
     public sealed class Semaphore :WaitHandle{
        //初始化信号量:初始请求数为initialCount,最大请求数为maximumCount
        public Semaphore(Int32 initialCount,Int32 maximumCount);
        public Int32 Release();//调用Release(1);返回上一个计数
        public Int32 Release(Int32 releaseCount);//返回上一个计数     
     }
    initialCount:就是初始化信号量时,解除阻塞的线程数。

    maximumCount:就是信号量允许执行的最大线程数。
     

      一个自动重置事件在行为上和最大计数为1的信号量非常相似。两者的区别在于,可以在一个自动重置事件上连续多次调用Set,同时仍然只有一个线程解除阻塞。相反,在一个信号量上连续多次调用Release,会使它的内部计数一直递增,这可能解除大量线程的阻塞。如果在一个信号量上多次调用Release,会导致它的计数超过最大计数,这是Release会抛出一个SemaphoreFullException.

      请看MSDN中的一个例子:

      

     1 using System;
     2 using System.Threading;
     3 
     4 public class Example
     5 {
     6     // A semaphore that simulates a limited resource pool.
     7     //
     8     private static Semaphore _pool;
     9 
    10     // A padding interval to make the output more orderly.
    11     private static int _padding;
    12 
    13     public static void Main()
    14     {
    15         // Create a semaphore that can satisfy up to three
    16         // concurrent requests. Use an initial count of zero,
    17         // so that the entire semaphore count is initially
    18         // owned by the main program thread.
    19         //初始化时允许解除的阻塞线程数量为0,最大的执行线程数为3,所以在第执行完第44行代码之前,开启的子线程中的代码都不会执行,如果注释掉第45行代码,这5个子线程都不会执行,如果改成:new Semaphore(1,3)初始化时允许解除的阻塞线程数量为1,最大执行的线程数为3,所以在执行完31行代码后会有一个子线程在运行的,如果注释掉第45行代码,就会只有一个信号量慢慢的运行完这5个子线程
    20         _pool = new Semaphore(0, 3);
    21 
    22         // Create and start five numbered threads. 
    23         //
    24         for (int i = 1; i <= 5; i++)
    25         {
    26             Thread t = new Thread(new ParameterizedThreadStart(Worker));
    27 
    28             // Start the thread, passing the number.
    29             //
    30             t.Start(i);
    31         }
    32 
    33         // Wait for half a second, to allow all the
    34         // threads to start and to block on the semaphore.
    35         //
    36         Thread.Sleep(500);
    37 
    38         // The main thread starts out holding the entire
    39         // semaphore count. Calling Release(3) brings the 
    40         // semaphore count back to its maximum value, and
    41         // allows the waiting threads to enter the semaphore,
    42         // up to three at a time.
    43         //
    44         Console.WriteLine("Main thread calls Release(3).");
    45         _pool.Release(3);//此句代码的通俗意思就是重新再增加3个可以执行的线程,如果初始化new semaphore(1,5)运行完这代代码就是1+3=4个线程数解除阻塞了,如果初始化为new  semaphore(0,5)运行完这段代码就是0+3=3个线程数解除阻塞了。
    46         //Console.WriteLine("_pool {0}", _pool.Release());
    47         //Console.WriteLine("_pool {0}", _pool.Release());
    48         //Console.WriteLine("_pool {0}", _pool.Release());
    49         //Console.WriteLine("_pool {0}", _pool.Release());
    50         //Console.WriteLine("_pool {0}", _pool.Release());
    51 
    52         Console.WriteLine("Main thread exits.");
    53 
    54        // Thread.Sleep(5000);
    55        // Console.WriteLine("_pool {0}", _pool.Release());
    56 
    57         Console.ReadLine();
    58     }
    59 
    60     private static void Worker(object num)
    61     {
    62         // Each worker thread begins by requesting the
    63         // semaphore.
    64         Console.WriteLine("Thread {0} begins " +
    65             "and waits for the semaphore.", num);
    66         _pool.WaitOne();
    67 
    68         // A padding interval to make the output more orderly.
    69         int padding = Interlocked.Add(ref _padding, 100);
    70 
    71         Console.WriteLine("Thread {0} enters the semaphore.", num);
    72 
    73         // The thread's "work" consists of sleeping for 
    74         // about a second. Each thread "works" a little 
    75         // longer, just to make the output more orderly.
    76         //模拟阻塞线程
    77          Thread.Sleep(1000 + padding);
    78 
    79         Console.WriteLine("Thread {0} releases the semaphore.", num);
    80         Console.WriteLine("Thread {0} previous semaphore count: {1}",
    81             num, _pool.Release());
    82     }
    83 }
    运行的其中之一的一个结果为:
    Thread 2 begins and waits for the semaphore.
    Thread 3 begins and waits for the semaphore.
    Thread 4 begins and waits for the semaphore.
    Thread 1 begins and waits for the semaphore.
    Thread 5 begins and waits for the semaphore.
    Main thread calls Release(3).
    Thread 5 enters the semaphore.
    Thread 5 releases the semaphore.
    Thread 5 previous semaphore count: 0
    Thread 1 enters the semaphore.
    Thread 1 releases the semaphore.
    Thread 1 previous semaphore count: 0
    Thread 3 enters the semaphore.
    Thread 3 releases the semaphore.
    Thread 3 previous semaphore count: 0
    Main thread exits.
    Thread 2 enters the semaphore.
    Thread 2 releases the semaphore.
    Thread 2 previous semaphore count: 1 //执行这段代码前。信号量(semaphore)中还有两个线程在执行(当前运行运行的线程和下面还没运行完的一个线程,所以剩余1个线程的信号量(semaphore)可以执行.
    Thread 4 enters the semaphore.
    Thread 4 releases the semaphore.
    Thread 4 previous semaphore count: 2 //执行这段代码前。信号量(semaphore)中有2个空闲的位置,可以执行线程了。

     这只是自己的理解,不正确的望各位大侠们指教。。。。。。。。。。。。。。。

  • 相关阅读:
    CodeForces 385C Bear and Prime Numbers 素数打表
    ZOJ 2853 Evolution 【简单矩阵快速幂】
    矩阵快速幂学习笔记
    USACO The Tamworth Two 模拟
    USACO Money Systems Dp 01背包
    UASCO Zero Sum DFS + Stack
    USACO Cow Pedigrees 【Dp】
    USACO Longest Prefix 【水】
    USACO Party Lamps 【Binary code solvution】【规律】
    USACO Runaround Numbers 模拟
  • 原文地址:https://www.cnblogs.com/huaan011/p/3578652.html
Copyright © 2020-2023  润新知