我希望能夠強制從一個線程切換到另一個線程的上下文。因此,我已實現了以下鎖定過程:強制線程上下文切換
#define TRUE (1==1)
#define FALSE (0==1)
#include <pthread.h>
int acquire(void);
int release(void);
int c_yield(int count);
// Who was the last to acquire the lock
static volatile pthread_t lock_owner;
// Is the lock currently taken
static volatile int lock_taken = FALSE;
/* This variable indicates how many threads are currently waiting for
* the lock. */
static volatile int lock_wanted = 0;
/* Mutex for protecting access to lock_wanted, lock_owner and
* lock_taken */
static pthread_mutex_t mutex;
/* Condition even to notify when the lock becomes available */
static pthread_cond_t cond;
void init_lock(void) {
pthread_cond_init(&cond, NULL);
pthread_mutex_init(&mutex, NULL);
}
int acquire(void) {
pthread_mutex_lock(&mutex);
if(lock_taken) {
lock_wanted++;
pthread_cond_wait(&cond, &mutex);
lock_wanted--;
}
if(lock_taken) {
pthread_mutex_unlock(&mutex);
return EPROTO;
}
lock_taken = TRUE;
lock_owner = pthread_self();
return pthread_mutex_unlock(&mutex);
}
int release(void) {
pthread_mutex_lock(&mutex);
lock_taken = FALSE;
if(lock_wanted > 0) {
pthread_cond_signal(&cond);
}
return pthread_mutex_unlock(&mutex);
}
使用另一種方法(未示出),然後我可以實現產率(),只有當有或者沒有線程等待鎖返回,或後至少有一個其他線程有機會運行。
這個實現大多數情況下工作正常,但是如果我用大約50個線程試圖以隨機間隔獲取和釋放鎖來進行壓力測試,每隔一段時間acquire()將返回EPROTO
,表示某人稱爲pthread_cond_signal
而不設置第一個lock_taken = FALSE
。
這是爲什麼?看起來好像CPU有時看不到lock_taken
的新值,這就是爲什麼我已經使變量變得不穩定。但它仍然發生......
謝謝!在等待的線程有機會抓住釋放的鎖之前,我看到另一個線程進入'acquire'的時刻。但是,您提到的「虛假喚醒」是否還有其他原因? * pthread_cond_signal(3)*表示它正在喚醒一個線程。在我的辯護中:我不相信'volatile'是必需的,但是我撒了他們以防萬一我錯了:-)。 – Nikratio
與'acquire'有同樣的問題可能會出現在* pthreads庫本身內部,無法控制。由於pthreads庫不能訪問謂詞,因此它不能在內部使用'while'循環。所以它有同樣的問題,但它無法解決它。 –
因此,* pthread_cond_signal(3)*顯然是錯誤的?這裏的描述似乎沒有考慮到你描述的可能性(但我還發現了其他幾個問題和關於虛假喚醒的維基百科文章,所以我傾向於相信你)。 – Nikratio