如何使Stack.Pop线程 [英] How to make Stack.Pop threadsafe

查看:309
本文介绍了如何使Stack.Pop线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的BlockingQueue code发布<一个href="http://stackoverflow.com/questions/2418188/multithreading-recommendation-based-on-program-description">in这个问题,但意识到我需要使用特定怎么我的程序运行队列的堆栈来代替。我将其转换为使用栈,并根据需要改名的类。出于性能我删除锁定在推,因为我的制片code是单线程的。

我的问题是如何可以跟帖工作的(现在的)线程安全的堆叠知道什么时候是空的。即使我添加另一个线程安全的包装器计数锁定底层集合类似的PUSH和POP做,我仍然会碰到访问计数,然后弹出是不是原子的竞争状态。

因为我看到他们可能的解决方案(这是preferred和我失去了任何会更好地工作?):

  1. 在消费者线程赶上抛出POP()的InvalidOperationException异常。
  2. 在pop()方法返回一个nullptr时_stack->计数== 0,然而C ++ - CLI没有默认的()运算符ALA C#
  3. 在pop()方法返回一个布尔值,并使用一个输出参数返回弹出元素。

下面是code,我使用的是现在:

 通用&LT; typename的T&GT;
公共引用类ThreadSafeStack
{
上市:
  ThreadSafeStack()
  {
    _stack = gcnew类别::通用::堆叠&LT; T&GT;();
  }

上市:
  无效推送(T元)
  {
    _stack-&GT;推(元);
  }

  牛逼流行(无效)
  {
    系统:线程::监视::输入(_stack);
    尝试 {
      返回_stack-&GT;流行();
    }
    最后 {
      系统:线程::监视::退出(_stack);
    }
  }

上市:
  物业诠释计数{
    INT GET(无效)
    {
      系统:线程::监视::输入(_stack);
      尝试 {
        返回_stack-&GT;计数;
      }
      最后 {
        系统:线程::监视::退出(_stack);
      }
    }
  }

私人:
  收藏集::通用::堆叠&LT; T&GT; ^ _stack;
};
 

解决方案

就个人而言,我会用你的选项3,但重命名此TryPop()。

这会使它更像框架的的 ConcurrentQueue&LT; T&GT;。.TryDequeue (在.NET 4中)


编辑:

我会这样声明:

 公开:
布尔TryPop([出] T%的结果);
 

在您的实现,您只需设置T值在方法的身体......

I am using the BlockingQueue code posted in this question, but realized I needed to use a Stack instead of a Queue given how my program runs. I converted it to use a Stack and renamed the class as needed. For performance I removed locking in Push, since my producer code is single threaded.

My problem is how can thread working on the (now) thread safe Stack know when it is empty. Even if I add another thread safe wrapper around Count that locks on the underlying collection like Push and Pop do, I still run into the race condition that access Count and then Pop are not atomic.

Possible solutions as I see them (which is preferred and am I missing any that would work better?):

  1. Consumer threads catch the InvalidOperationException thrown by Pop().
  2. Pop() return a nullptr when _stack->Count == 0, however C++-CLI does not have the default() operator ala C#.
  3. Pop() returns a boolean and uses an output parameter to return the popped element.

Here is the code I am using right now:

generic <typename T>
public ref class ThreadSafeStack
{
public:
  ThreadSafeStack()
  {
    _stack = gcnew Collections::Generic::Stack<T>();
  }

public:
  void Push(T element)
  {
    _stack->Push(element);
  }

  T Pop(void)
  {
    System::Threading::Monitor::Enter(_stack);
    try {
      return _stack->Pop();
    }
    finally {
      System::Threading::Monitor::Exit(_stack);
    }
  }

public:
  property int Count {
    int get(void)
    {
      System::Threading::Monitor::Enter(_stack);
      try {
        return _stack->Count;
      }
      finally {
        System::Threading::Monitor::Exit(_stack);
      }
    }
  }

private:
  Collections::Generic::Stack<T> ^_stack;
};

解决方案

Personally, I would use your option 3., but rename this TryPop().

This would make it behave more like the Framework's ConcurrentQueue<T>.TryDequeue (in .NET 4).


Edit:

I'd declare it like so:

public:
bool TryPop([Out] T% result);

In your implementation, you just set the T value in your method body...

这篇关于如何使Stack.Pop线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆