如何使Stack.Pop线程线程、Stack、Pop

由网友(8.被自己宠坏的小仙女)分享简介:我使用的BlockingQueue code发布in这个问题,但意识到我需要使用特定怎么我的程序运行队列的堆栈来代替。我将其转换为使用栈,并根据需要改名的类。出于性能我删除锁定在推,因为我的制片code是单线程的。我的问题是如何可以跟帖工作的(现在的)线程安全的堆叠知道什么时候是空的。即使我添加另一个线程安全的包装器计...

我使用的BlockingQueue code发布in这个问题,但意识到我需要使用特定怎么我的程序运行队列的堆栈来代替。我将其转换为使用栈,并根据需要改名的类。出于性能我删除锁定在推,因为我的制片code是单线程的。

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

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

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

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

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

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

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

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

私人:
  收藏集::通用::堆叠< T> ^ _stack;
};
 

解决方案

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

Stack and Pop手机版 Stack and Pop游戏下载

这会使它更像框架的的 ConcurrentQueue< T>。.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?):

Consumer threads catch the InvalidOperationException thrown by Pop(). Pop() return a nullptr when _stack->Count == 0, however C++-CLI does not have the default() operator ala C#. 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...

阅读全文

相关推荐

最新文章