zoukankan      html  css  js  c++  java
  • 编程之美--信号量与互斥锁选择(转)

    分类: C/C++

    基本的思路
      这个问题相当于是生产者和消费者模型的问题
      首先定义两个线程,一个是下载线程,一个是存储线程,下载线程将数据从网络上下载到相应的数据的缓冲区中(BLOCK组成的队列)。存储的线程从数据缓冲区中读取相应的数据,并将其写到相应的磁盘上去。
      多线程同步的方式有:CriticalSection、Mutex和Semaphore(信号量)。因为CriticalSection和Mutex,将不会使下载线程和存储线程同时进行工作,影响系统的效率,所以这里采用semaphore。
    信号量的含义:
    信号量的特性如下:信号量是一个非负整数(表示可以利用的资源数,这里是指的是可用的数据缓冲区中BLOCK的数量),所有通过它的线程(下载线程和存储线程)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作:Unsignal 和 Signal(释放)。 当一个线程调用Unsignal操作时,它要么通过然后将信号量减一(还有相应的资源),要么一直等下去(相应的资源已经没有),直到信号量大于一或超时。Signal实际上是在信号量上执行加操作,相当于提醒别的新的线程已经可以使用被释放的资源。       
    核心程序
    #define BUFFER_COUNT 100  //定义数据队列中数据块的数目。
    //每一个数据块将是下载线程和存储线程操作的基本的单元
    BLOCK g_buffer[BUFFER_COUNT];//数据缓冲区队列
     
    Thread g_ThreadA(ProcA);//下载线程
    Thread g_ThreadB(ProcB);//存储线程
    //信号量,表示现在在数据队列中已经存放满数据的数据块的数量
    Semaphore g_seFull(0,BUFFER_COUNT);
    //信号量,表示现在在数据队列中空数据块的数量
    Semaphore g_seEmpty(BUFFER_COUNT,BUFFER_COUNT);
    bool g_downloadComplete = false;
    int in_index = 0;//表示当前下载线程正在处理的数据块的编号
    int out_index = 0;//表示当前存储线程正在处理的数据块的编号
     
    void main()
    {
         g_ThreadA.start();//启动下载线程
         g_ThreadB.start();//启动存储线程
         Wait();
    }
     
    //下载线程的工作函数
    void ProcA()
    {
         while(true)
         {
               //申请一个空的数据块的资源
              g_seEmpty.Unsignal();  
              //申请到空的数据块,向in_index指向的BLOCK下载数据
              g_downloadComplete = GetBlockFromNet(g_buffer + in_index);
              //in_index更新
              in_index = (in_index + 1) % BUFFER_CONUT;  
              g_seFull.Signal();//报告又有一个新的数据块已经下载完毕,可以指向写入操作...
             if(g_downloadComplete)
                    break;
         }
    }
     
    //存储线程的工作函数
    void ProcB()
    {
         while(true)
         {
               //申请一个满的数据块的资源
              g_seFull.Unsignal();  
              //申请到满的数据块,从out_index指向的BLOCK获取数据,写入Disk。
              WriteBlockToDisk(g_buffer + out_index);
              //out_index更新
              out_index = (out_index + 1) % BUFFER_CONUT;  
              g_seEmpty.Signal();//报告又有一个新的数据块已经写入完毕,可以下载覆盖其数据...
             if(g_downloadComplete && out_index == in_index)
                   break;
         }
    }
     
  • 相关阅读:
    AJPFX总结mysql复制表结构,表数据
    AJPFX总结IO流中的缓冲思想
    AJPFX学习Java函数知识总结
    AJPFX总结面向对象特征之一的继承知识
    AJPFX学习笔记JavaAPI之String类
    AJPFX:学习JAVA程序员两个必会的冒泡和选择排序
    AJPFX:关于面向对象及java的一些机制的思考
    ES6 入门系列
    Android studio工具介绍
    获得 LayoutInflater 实例的三种方式
  • 原文地址:https://www.cnblogs.com/heyp/p/3791390.html
Copyright © 2011-2022 走看看