互斥锁测试代码异常咨询:为何未输出预期内容?
Hey there! Let's break down why your code isn't outputting the full expected message, and walk through how to fix it.
First, let's recap your problem:
You're learning mutex locks, wrote test code that should output
downloading..... complete.... start play!, but only getdownloading..... complete..... You want to know:
- What's causing the error?
- How to fix the code?
Based on common pitfalls with pthread condition variables and your code snippet, here's the breakdown:
1. Why Your Code Isn't Working
The core issue almost certainly boils down to missing condition variable signaling plus potential misuses of locks/condition checks:
- No wake-up for the play thread: Your
downloadthread finishes updating the shared state (buffer) but never tells the waitingplaythread that it's ready. Theplaythread gets stuck waiting indefinitely onpthread_cond_wait(), so it never prints "start play!". - Possible lock misuse: If you're modifying
bufferwithout holding the mutex, you create a data race, and theplaythread might never see the updated value even if you did signal. - Using
ifinstead ofwhilefor condition checks: Even if you added a signal, usingifcould lead to spurious wakeups (rare but allowed by pthread specs) causing unexpected behavior, but the immediate block here is the missing signal.
2. Fixed Code & Explanations
Here's the corrected version of your code, with key fixes highlighted:
#include <stdio.h> #include <pthread.h> #include <unistd.h> int buffer = 0; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; void* download(void *arg) { // Simulate download work (no lock needed here since we're not touching shared data) printf("downloading..... "); sleep(2); // Lock before modifying shared buffer to avoid race conditions pthread_mutex_lock(&lock); buffer = 1; // Mark download as complete printf("complete....\n"); // Signal the waiting play thread that the buffer is ready pthread_cond_signal(&cond); // Unlock after signaling (order doesn't matter here, but unlock when done with shared data) pthread_mutex_unlock(&lock); return NULL; } void* play(void *arg) { pthread_mutex_lock(&lock); // Use WHILE loop to check condition (critical for handling spurious wakeups) while (buffer == 0) { // Wait releases the lock temporarily, and re-acquires it when woken pthread_cond_wait(&cond, &lock); } // Now we know buffer is ready, print the message printf("start play!\n"); pthread_mutex_unlock(&lock); return NULL; } int main() { pthread_t tid1, tid2; pthread_create(&tid1, NULL, download, NULL); pthread_create(&tid2, NULL, play, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(&lock); pthread_cond_destroy(&cond); return 0; }
Key Fixes:
- Added
pthread_cond_signal()indownload: This wakes up the waitingplaythread once the download is done and the buffer is updated. - Protected shared
bufferaccess with mutex: Any read/write tobufferhappens while holding the mutex, preventing data races and ensuring visibility of updates across threads. - Replaced
ifwithwhileinplay: This handles spurious wakeups (where the thread wakes up without being signaled) by re-checking the condition before proceeding.
When you run this fixed code, you'll get your expected output:
downloading..... complete.... start play!
内容的提问来源于stack exchange,提问作者Eunjeong Choi

