Visual C++中如何实现两个线程独立并发运行?
Alright, let's get your threads running independently instead of serially. The root issue in your original code is that you're holding the semaphore while the thread sleeps—this blocks the other thread entirely until the sleeping thread releases the lock. We need to restructure the code so that only the critical operations (modifying the shared integer and writing to the console) are protected, not the sleep period.
Here's the revised code with explanations of the key changes:
using namespace System; using namespace System::Threading; public ref class RunStack { private: static Semaphore^ stackSemaphor; static int itemStack = 10; // Use a single shared Random instance to avoid duplicate random sequences static Random^ sharedRand = gcnew Random(); public: static void addItem() { while (true) { // Generate sleep time and wait BEFORE acquiring the lock int pause = sharedRand->Next(1, 10) * 1000; Thread::Sleep(pause); // Only lock for the critical section: modifying the shared value and console output stackSemaphor->WaitOne(); try { itemStack++; Console::CursorLeft = 3; Console::CursorTop = 3; Console::WriteLine("Amount in stack: " + itemStack); } finally { // Ensure we always release the semaphore even if something goes wrong stackSemaphor->Release(); } } } public: static void subItem() { while (true) { // Sleep first without holding the lock int pause = sharedRand->Next(1, 10) * 1000; Thread::Sleep(pause); stackSemaphor->WaitOne(); try { itemStack--; Console::CursorLeft = 3; Console::CursorTop = 3; Console::WriteLine("Amount in stack: " + itemStack); } finally { stackSemaphor->Release(); } } } void Main() { stackSemaphor = gcnew Semaphore(1, 1); Thread^ thread1 = gcnew Thread(gcnew ThreadStart(addItem)); thread1->Priority = ThreadPriority::Normal; thread1->Start(); Thread^ thread2 = gcnew Thread(gcnew ThreadStart(subItem)); thread2->Priority = ThreadPriority::Normal; thread2->Start(); } }; int main(array<System::String ^> ^args) { Console::Title = "ItemStack"; RunStack^ runIt = gcnew RunStack(); runIt->Main(); return 0; }
Key Changes Explained:
Moved Sleep Outside the Critical Section
By sleeping before acquiring the semaphore, the thread doesn't hold the lock while it's waiting. This lets the other thread execute its critical section multiple times if the first thread is asleep.Shared Random Instance
Creating aRandominstance per thread can lead to identical random sequences if threads start at nearly the same time. Using a single shared instance ensures more varied sleep times. (Note:Random::Nextis thread-safe for basic usage here, but you could add a lock around it if you need strict thread safety.)Try/Finally Block for Semaphore Release
This guarantees the semaphore is always released, even if an unexpected error occurs during the critical section. It's a best practice to prevent deadlocks.
Now when you run the code, you'll see that one thread can perform multiple add or subtract operations while the other is sleeping—exactly the independent execution you wanted.
内容的提问来源于stack exchange,提问作者PQuix

