現在已修復。我已經增加了一個程序來顯示它是如何修復的。該程序旨在演示在多線程環境中信號如何丟失。這種信號損失會導致競爭狀態。阻塞線程永遠不會獲取解鎖信號,因爲它會錯過信號。這有條件,和互斥。解決這類問題的方法是使用cond_var。 cond_var保護條件以及數據。因此,它會自動鎖定條件,一旦其他線程發出信號就會解除條件。條件鎖定可以防止信號遺漏。錯誤的程序 - 比賽條件程序被添加到這裏。如何在Linux中傳遞信號以解除暫停()?
我有以下程序。我試圖通過電話解鎖它 - 殺人。但是,我的程序掛起,因爲它永遠不會發送信號給阻塞的函數()。我不想使用pthread_cond,因爲我想在這裏演示這個問題。但是信號不會丟失,但它永遠不會通過信號來解鎖它。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
/** get pid **/
#include <sys/types.h>
#include <unistd.h>
/** kill signal **/
#include <signal.h>
using namespace std;
int shared_variable = 7;
pid_t pid_A;
pid_t pid_B;
class helium_thread
{
private:
pthread_t *thread_id;
pid_t process_pid;
public:
static pthread_mutex_t mutex_thread;
void set_thread_id(pthread_t tid);
pthread_t *get_thread_id();
int create_thread(pthread_t *thread_ptr, const pthread_attr_t *attr, void * (*start_routine)(void *), void *arg);
helium_thread();
~helium_thread();
};
helium_thread thread_1, thread_2;
void helium_thread::set_thread_id(pthread_t tid)
{
*(this->thread_id) = tid;
}
pthread_t * helium_thread::get_thread_id()
{
return (this->thread_id);
}
int helium_thread::create_thread(pthread_t *thread_ptr, const pthread_attr_t *attr, void * (*start_routine)(void *), void *arg)
{
int ret;
ret = pthread_create(thread_ptr,attr,start_routine,(void *)arg) ;
cout<<"Thread created "<<std::hex<<thread_ptr<<endl;
return ret;
}
helium_thread::helium_thread()
{
thread_id = new pthread_t;
cout<<"Constructor called "<<std::hex<<thread_id<<endl;
}
helium_thread::~helium_thread()
{
cout<<"Destructor called"<<std::hex<<thread_id<<endl;
delete thread_id;
}
/** While defining the methods of the class, Keywords static and virtual should not be repeated in the definition. **/
/** They should only be used in the class declaration. **/
void *Thread_Function_A(void *thread_arg)
{
int rc = 0;
pthread_mutex_lock(&(helium_thread::mutex_thread));
pid_A = getpid();
cout<<"The pid value of Thread A is"<< pid_A << endl;
if (shared_variable == 5)
{
shared_variable = 100;
cout<<"The thread A proceeds"<<endl;
pthread_mutex_unlock(&(helium_thread::mutex_thread));
}
else
{ pthread_mutex_unlock(&(helium_thread::mutex_thread));
cout<<"Going to block now"<<endl;
rc = pause();
cout<<"Unblocked now, the rc value is "<<rc<<endl;
}
}
void *Thread_Function_B(void *thread_arg)
{
pthread_mutex_lock(&(helium_thread::mutex_thread));
pid_B = getpid();
cout<<"The pid value of Thread B is"<< pid_B << endl;
shared_variable = 5;
cout<<"Unblock the thread A now"<<endl;
pthread_kill(*(thread_1.get_thread_id()), SIGCONT);
pthread_mutex_unlock(&(helium_thread::mutex_thread));
}
/** The definition of the static member can't be inside a function, You need to put it outside **/
/** When I tried using inside a function, I got the error - error: invalid use of qualified-name ‘helium_thread::mutex_thread **/
pthread_mutex_t helium_thread::mutex_thread = PTHREAD_MUTEX_INITIALIZER;
int main(int argc, char *argv[])
{
pid_t thread_pid_val = getpid();
thread_1.create_thread((thread_1.get_thread_id()),NULL,Thread_Function_A,&thread_pid_val);
thread_2.create_thread((thread_2.get_thread_id()),NULL,Thread_Function_B,&thread_pid_val);
pthread_join(*(thread_1.get_thread_id()), NULL);
pthread_join(*(thread_2.get_thread_id()), NULL);
return 0;
}
輸出是 -
$ ./thread_basic.out
Constructor called 0x195c010
Constructor called 0x195c030
Thread created 0x195c010
The pid value of Thread A is404c
Thread created Going to block now
The pid value of Thread B is0x404c
Unblock the thread A now
0x195c030
------------------工作種族 - 條件
計劃專#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
/** get pid **/
#include <sys/types.h>
#include <unistd.h>
/** kill signal **/
#include <signal.h>
using namespace std;
int shared_variable = 7;
pid_t pid_A;
pid_t pid_B;
class helium_thread
{
private:
pthread_t *thread_id;
pid_t process_pid;
public:
static pthread_mutex_t mutex_thread;
void set_thread_id(pthread_t tid);
pthread_t *get_thread_id();
int create_thread(pthread_t *thread_ptr, const pthread_attr_t *attr, void * (*start_routine)(void *), void *arg);
helium_thread();
~helium_thread();
};
helium_thread thread_1, thread_2;
void helium_thread::set_thread_id(pthread_t tid)
{
*(this->thread_id) = tid;
}
pthread_t * helium_thread::get_thread_id()
{
return (this->thread_id);
}
int helium_thread::create_thread(pthread_t *thread_ptr, const pthread_attr_t *attr, void * (*start_routine)(void *), void *arg)
{
int ret;
ret = pthread_create(thread_ptr,attr,start_routine,(void *)arg) ;
cout<<"Thread created "<<std::hex<<thread_ptr<<endl;
return ret;
}
helium_thread::helium_thread()
{
thread_id = new pthread_t;
cout<<"Constructor called "<<std::hex<<thread_id<<endl;
}
helium_thread::~helium_thread()
{
cout<<"Destructor called"<<std::hex<<thread_id<<endl;
delete thread_id;
}
/** While defining the methods of the class, Keywords static and virtual should not be repeated in the definition. **/
/** They should only be used in the class declaration. **/
void handler(int sig)
{
//do nothing
cout<<"Handler called"<<endl;
}
void *Thread_Function_A(void *thread_arg)
{
int rc = 0;
pthread_mutex_lock(&(helium_thread::mutex_thread));
pid_A = getpid();
cout<<"The pid value of Thread A is"<< pid_A << endl;
while(1)
{
if (shared_variable == 5)
{
shared_variable = 100;
cout<<"The thread A proceeds"<<endl;
cout<<"The shared_variable value = "<< std::dec<< shared_variable << endl;
pthread_mutex_unlock(&(helium_thread::mutex_thread));
cout<<"The thread exits"<<endl;
pthread_exit(NULL);
}
else
{ pthread_mutex_unlock(&(helium_thread::mutex_thread));
cout<<"Going to block now"<<endl;
/** This sleep will give a sufficient time to schedule thread B **/
/** Once thread B is scheduled, the thread B will sent a signal to unblock the thread A **/
/** The signal has been sent, but this thread was not in the pause instruction **/
sleep(5);
cout<<"Sleep completed now"<<endl;
/** Thread B has sent the signal; and it may be lost **/
/** The pause will be blocked now, waiting for the signal to occur again **/
rc = pause();
cout<<"Unblocked now, the rc value is "<<rc<<endl;
}
}
}
void *Thread_Function_B(void *thread_arg)
{
pthread_mutex_lock(&(helium_thread::mutex_thread));
pid_B = getpid();
cout<<"The pid value of Thread B is"<< pid_B << endl;
shared_variable = 5;
cout<<"Unblock the thread A now"<<endl;
pthread_kill(*(thread_1.get_thread_id()), SIGUSR1);
pthread_mutex_unlock(&(helium_thread::mutex_thread));
cout<<"Return thread function b now"<<endl;
}
/** The definition of the static member can't be inside a function, You need to put it outside **/
/** When I tried using inside a function, I got the error - error: invalid use of qualified-name ‘helium_thread::mutex_thread **/
pthread_mutex_t helium_thread::mutex_thread = PTHREAD_MUTEX_INITIALIZER;
int main(int argc, char *argv[])
{
pid_t thread_pid_val = getpid();
/** Install signal handler **/
signal(SIGUSR1, handler);
thread_1.create_thread((thread_1.get_thread_id()),NULL,Thread_Function_A,&thread_pid_val);
thread_2.create_thread((thread_2.get_thread_id()),NULL,Thread_Function_B,&thread_pid_val);
pthread_join(*(thread_1.get_thread_id()), NULL);
pthread_join(*(thread_2.get_thread_id()), NULL);
return 0;
}
的輸出如下。
$ ./thread_basic.out
Constructor called 0x1e01010
Constructor called 0x1e01030
Thread created 0x1e01010
The pid value of Thread A is45a6
Going to block now
Thread created 0x1e01030
The pid value of Thread B is45a6
Unblock the thread A now
Return thread function b now
Handler called
Sleep completed now
謝謝,我應該實際上使用pthread_cond。我的目的是用這些代碼來證明競爭條件。這個問題實際上產生了一個解決方案 - cond_var。因此,有必要證明這個問題。我已經證明了這個問題。在代碼中查看我的意見。 –
@SHREYAS JOSHI,我刪除了關於競賽情況的評論,因爲我並不是100%確定那是發生了什麼事情。我認爲@fibonacci遇到了這個問題。 'pause'只會從調用處理函數或終止進程的信號中返回。由於沒有處理程序,'SIGCONT'的默認值對於未關閉(而不是「已暫停」)過程是忽略信號,我認爲過程從未看到信號。如果你打算去追求它,可能會更值得玩一玩。 – Duck
我從我的代碼中刪除了睡眠,我發現信號完全沒有被遺漏。編寫這個比賽條件程序的整個想法是爲了證明爲什麼需要條件變量。如果你在線程A中嘗試了第二個帶睡眠的程序,並在線程B中睡眠,你會看到信號有時會丟失,有時不會。因此,這個程序是不可靠的。這是一個很好的競爭條件的例子。 –