If you are doing this for self-education, great - otherwise BlockingCollection<T> or ConcurrentQueue<T> are good alternatives.
One problem I do see here is that there is no way to interrupt Pop once it starts - it assumes an object is waiting when it awakens. How would you clear this down on termination? A TryPop that returns true (with an element) or false (if no data) might be better, then you could signal waiting threads to shut down cleanly once the queue is drained.