簡單地說,在單一生產者 - 單一消費者場景下,我使用可變對象進行同步,並在生產者和消費者之間傳遞數據和消息。共享緩衝區是字節數組的一個ConcurrentQueue
。爲了實現一個循環緩衝區並通過GC
阻止堆碎片和頻繁對象交換,我使用了字節數組的ConcurrentBag
作爲用於所使用的字節數組的回收站。 ManualResetEventSlim
用於線程同步。有時我會在代碼中失去對字節數組的引用。下面是我的代碼的簡化版本,以防您需要更多細節,但我想這是使用線程時的常規錯誤。多線程中的變量範圍,爲什麼我的對象引用丟失?
MutableObject mutableObject = new MutableObject();
Producer producer = MutableObject.GetProducer();
Consumer consumer = MutableObject.GetConsumer();
Thread fork = new Thread(new ThreadStart(producer.Start));
// Forking execution path
fork.Start();
// Main thread goes here
consumer.Start();
class MutableObject()
{
private Producer m_producer;
private Consumer m_consumer;
private ConcurrentBag<byte[]> m_recycleBin = new ConcurrentBag<byte[]>();
private ConcurrentQueue<byte[]> m_sharedBuffer = new ConcurrentQueue<byte[]>();
public Producer GetProducer()
{
// Keep a reference to the mutable object
return new Producer(this);
}
// GetConsumer() method is just like GetProducer() method
public void GetEmptyBuffer(out byte[] buffer)
{
if (!m_recycleBin.TryTake(out buffer))
buffer = new byte[1024];
}
public bool Put(byte[] buffer)
{
m_sharedBuffer.Enqueue(buffer);
// Set ManualResetEventSlim for consumer
}
public bool Get(byte[] buffer) // Consumer calls this method in a loop
{
m_sharedBuffer.TryDequeue(out buffer);
// I save a reference to buffer here and pass it to recyclebin at next call like this: lastBuffer = buffer;
// This is because buffers are passing by refrence for I should wait until it would be used by consumer.
m_recycleBin.Add(lastBuffer);
// Set ManualResetEventSlim for producer
}
}
class Producer
{
private MutableObject m_mutableObject;
public Producer(MutableObject mutableObject)
{
m_mutableObject = mutableObject;
}
public void Start()
{
byte[] buffer;
while (true)
{
m_mutableObject.GetEmptyBuffer(out buffer);
m_mutableObject.Put(buffer);
}
}
}
其實GetEmptyBuffer()
方法經常造成新的緩衝區,雖然使用的緩衝區存儲在回收斌,回收斌計數有時不養!
如果我在哪裏,我會擔心堆碎片等,一旦我得到代碼*工作*。 – aioobe 2010-10-25 19:16:17
recylceBin何時清空? – 2010-10-25 19:28:05
這段代碼實際上工作嗎?正如我所看到的,它不應該編譯。 – 2010-10-25 19:33:08