一个线程写一个线程读的队列

 

 

一个线程读,另一个线程写的队列.

没有经过测试, 如果有什么bug,欢迎指正

#include  < list >
#include 
< Windows.h >

//  gegerator a null handle
template  < typename HandleType >
struct  null_handle_generator
{
    
static HandleType get()
    
{
        
return static_cast<HandleType>(0);
    }

}
;

/**
 *    仅一个线程读一个线程写的list
 
*/

template
<  typename T, typename NullGenerator = null_handle_generator < T >   >
class  CSingleReadSingleWriteList
{
    std::list
<T> m_list; ///<存储T的双向链表
    CRITICAL_SECTION m_cs; ///<对list的线程保护
    HANDLE m_hEvent; ///<get()堵塞等待时等待的事件
    bool m_bWaiting; ///<get()是否在堵塞等待
    bool m_bInitSucc; ///<是否成功初始化
    bool m_bCancelWait; ///<是否取消get()的堵塞

public:
    CSingleReadSingleWriteList(
void):
      m_bWaiting( 
false ),
      m_hEvent( NULL ),
      m_bInitSucc( 
false ).
      m_bCancelWait( 
false )
    
{
    }


    
virtual ~CSingleReadSingleWriteList(void)
    
{
        
if( m_bInitSucc )
        
{
            SAFE_CLOSEHANDLE( m_hEvent );
            DeleteCriticalSection( 
&m_cs );
        }

    }


    
/**
     *    初始化使用队列必须的成员。
     *    如果初始化失败,不能使用CSingleReadSingleWriteList,调用GetLastError()查具体原因
     
*/

    
bool init()
    
{
        
if( ::InitializeCriticalSectionAndSpinCount( &m_cs, 0x80000400 ) )
        
{
            m_hEvent 
= CreateEvent( NULL, FALSE, FALSE, NULL );
            m_bInitSucc 
= true;
        }

        
return m_bInitSucc;
    }


    
/**
     *    以堵塞的方式从队列中取一个元素
     
*/

    T 
get()
    
{
        
if!m_bInitSucc ) return NULLGenerator::get();

        EnterCriticalSection( 
&m_cs );
        
if( m_list.size() == 0 ) m_bWaiting = true;
        LeaveCriticalSection( 
&m_cs );

        
if( m_bWaiting )
        
{
            
if( m_hEvent )
            
{
                WaitForSingleObject( m_hEvent, INFINITE );
            }

            
else
            
{
                
while( m_list.size() == 0 && !m_bCancelWait )
                
{
                    Sleep( 
1 );
                }

            }

            m_bWaiting 
= false;
        }


        EnterCriticalSection( 
&m_cs );
        
if( m_list.size() == 0 )
        
{
            LeaveCriticalSection( 
&m_cs );
            
//仅在不希望以后再调get了,队列将销毁时才可能进入这里,
            
//返回T的无效值,调用者在得到无效值时,以后不应该在调用这个实例的任何方法
            return NULLGenerator::get();
        }

        T t 
= m_list.front();
        m_list.pop_front();
        
if( m_hEvent && m_list.size() == 0 ) ResetEvent( m_hEvent );
        LeaveCriticalSection( 
&m_cs );
        
return t;
    }


    
/**
     *    向队列填入一个元素
     
*/

    
void put( T t )
    
{
        
//不允许填入无效的T值到队列
        if!m_bInitSucc || t == NULLGenerator::get() ) return;

        EnterCriticalSection( 
&m_cs );

        m_list.push_back( t );
        
if( m_bWaiting && m_hEvent && m_list.size()==1 )
        
{
            SetEvent( m_hEvent );
        }


        LeaveCriticalSection( 
&m_cs );
    }


    
/**
     *    如果get堵塞,需要调用取消堵塞。比如在需要使get线程退出,但get被堵住时
     
*/

    
void cancelGet()
    
{
        
if!m_bInitSucc ) return;

        EnterCriticalSection( 
&m_cs );
        
if( m_bWaiting && m_hEvent && m_list.size()==0 )
        
{
            SetEvent( m_hEvent );
        }

        m_bCancelWait 
= true;
        LeaveCriticalSection( 
&m_cs );
    }

}
;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 你可以使用 Python 中的 Queue 模块中的 Queue 类来创建一个线程安全的队列。这个类在线程间提供了同步机制,使得你可以在多个线程之间安全地使用一个队列。 下面是一个例子,展示了如何使用 Queue 类来创建一个线程安全的队列: ``` import queue q = queue.Queue() # 在队列中添加一个元素 q.put('a') # 从队列中取出一个元素 item = q.get() print(item) # 输出: 'a' # 在队列中添加多个元素 q.put('b') q.put('c') # 使用循环来从队列中取出多个元素 while not q.empty(): print(q.get()) # 输出: 'b' 'c' ``` 需要注意的是,Queue 类是由 Python 中的 threading 模块提供的,所以你需要先导入这个模块才能使用。 ### 回答2: 线程安全的队列是一种能够在多个线程同时访问时,不会出现数据竞争或数据损坏的数据结构。以下是一个简单的线程安全的队列的实现: ```java public class ThreadSafeQueue<T> { private Queue<T> queue; public ThreadSafeQueue() { queue = new LinkedList<>(); } public synchronized void enqueue(T item) { queue.add(item); notifyAll(); } public synchronized T dequeue() throws InterruptedException { while (queue.isEmpty()) { wait(); } return queue.poll(); } public synchronized boolean isEmpty() { return queue.isEmpty(); } public synchronized int size() { return queue.size(); } } ``` 这个实现使用Java的内置队列数据结构,并使用`synchronized`关键字来确保在多线程环境下的安全访问。`enqueue`方法和`dequeue`方法都用`synchronized`关键字修饰,以确保同时只有一个线程可以对队列进行入队或出队操作。当一个线程调用`enqueue`方法时,它会将元素添加到队列并通过`notifyAll`方法通知其他等待线程。当一个线程调用`dequeue`方法时,如果队列为空,它将进入等待状态,直到有其他线程调用`enqueue`方法并通知它。这样可以避免在空队列上进行出队操作。另外,`isEmpty`和`size`方法也用`synchronized`关键字修饰,以确保在多线程环境下获取正确的队列状态。 这个线程安全的队列的实现保证了多个线程在并发访问时不会出现数据竞争或数据损坏的问题,从而可以安全地用于多线程的应用场景中。 ### 回答3: 线程安全的队列是一种多线程环境下能够保证数据操作安全的数据结构。在实现线程安全队列时,可以考虑使用互斥锁(mutex)或者锁(read-write lock)来保护队列的数据结构,以确保在多线程操作时数据的一致性和完整性。 在实现一个线程安全队列时,可以定义一个队列类,并在其内部维护一个数据结构(如数组或链表)来存储数据元素。以下为一个可能的实现: ```python import threading class ThreadSafeQueue: def __init__(self): self.queue = [] self.mutex = threading.Lock() def enqueue(self, item): with self.mutex: self.queue.append(item) def dequeue(self): with self.mutex: if self.is_empty(): return None return self.queue.pop(0) def is_empty(self): return len(self.queue) == 0 def size(self): return len(self.queue) ``` 在上述代码中,使用了互斥锁`mutex`来保证在队列的入队和出队操作时只有一个线程可以进行操作。通过`with self.mutex`语句块包裹队列操作,可以确保在操作期间其他线程无法同时访问队列,从而保证队列操作的原子性。 这里的队列是使用数组实现的,`enqueue()`方法通过`append()`将元素添加到队列的末尾,`dequeue()`方法使用`pop(0)`取出队列的头部元素并返回。`is_empty()`和`size()`方法分别返回队列是否为空和队列的大小。 通过以上的实现,可以确保在多线程环境下,对队列的操作和数据的访问是互不干扰的,从而保证了线程安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值