多线程队列的实现有关问题

多线程队列的实现问题?
看了一些多线程队列的例子,

用到了互斥体或者临界区, 最重要的内核对象,还有信号量

问题:为什么要使用 信号量?

一种内核对象,不够吗?

保证每次只有一个线程在访问 该队列的成员,比如头,尾指针,还有队头元素,队尾元素。

不断可以节省 内核对象,减轻代码复杂性。

事实上,很多例子,都增加了 信号量。

原因是什么?

具体的说,什么函数里使用信号量呢?

比如, get函数。

get的时候,先wait,然后,取元素,取完毕,就释放元素,释放的过程中,肯定加锁(用上文提到的临界区或者互斥体实现)。


为什么,要wait?

伪代码如下:


template <class T>
void CMyQueue< T >::Get(T &buf)
{
pOccupiedSema.Wait(); //内部waitforsingleobject
int ntest = 0;
MyGet(buf); ///内部lock 
}



template <class T>
void CMyQueue< T >::Put(T &newData)
{
if( IsOccupied() )
return  ;
MyPut(newData);  //lock
pOccupiedSema.Post();  //内部releaseseampore
}


------解决方案--------------------
引用:
Quote: 引用:

信号量只不过是对特殊区域码段的量化同步执行,当然可以用互斥和临界区加个自定义变量作信号量来代替实现,说不定其内部就是这么实现的呢,纠结这个有意思么?
好比beginthread可以创建线程,为什么还有createthread也可创建线程。
人家提供给你了多个东西,可实现相同的功能,可能有细微区别,你爱用哪个用哪个。


信号量放这里,有什么作用?


用处当然是有的。
伪代码简单举个例,有三个线程,共用一个内核对象:
先用事件HEvent hEvent,自动重置事件
线程1
{
        SetEvent(hEvent);
}

线程2
{
      WaitForSinleObject(hEvent,0xFFFFFFFF);
      {
             //执行一些较复杂的代码段2
      }
      SetEvent(hEvent);
}

线程3
{
      WaitForSinleObject(hEvent,0xFFFFFFFF);
      {
             //执行一些较复杂的代码段3
      }
      SetEvent(hEvent);
}

当在线程1中SetEvent(hEvent)后,线程2的代码段2和线程3中的代码段3只能有其中一个先执行,执行完了后另一个才能执行,即所谓的同步。

而如果改用信号量HANDLE hSemaphore = ::CreateSemaphore(NULL, 0, 2, NULL); 

线程1
{
        ReleaseSemaphore(hSemaphore,2,0); //增加2个信号量
}

线程2
{
      WaitForSinleObject(hSemaphore,0xFFFFFFFF);  //使用1个信号量
      {
             //执行一些较复杂的代码段2
      }
}

线程3
{
      WaitForSinleObject(hSemaphore,0xFFFFFFFF);//使用1个信号量
      {
             //执行一些较复杂的代码段3
      }
 }

这样的话,代码段2和代码段3是异步执行的。


以上是2个线程等待另1线程的信号的情况,再说个1个线程等待2个线程的信号的情况。

线程1
{
        ReleaseSemaphore(hSemaphore,1,0); //增加1个信号量
}

线程2
{
     ReleaseSemaphore(hSemaphore,1,0); //增加1个信号量
}

线程3
{
     while(true)
     {
           WaitForSinleObject(hSemaphore,0xFFFFFFFF);//使用1个信号量
      {
             //执行一些较复杂的代码段3
           }
     }
 }

代码段3能执行2次。如果改用事件,在线程1和线程2的SetEvent趋于同时的时候,代码段3可能就只执行1次了。