I'm new to threads and seem to be having a timing problem. When I run my code my output is...
Data received!
Data processed!
and then it just hangs. I assume I'm using wait and signal incorrectly. Help would be greatly appreciated.
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
char buffer [100];
pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER;
void* threadFunc(void *proc){
if((int)proc == 0){
pthread_mutex_lock(&buffer_mutex);
sprintf(buffer, "Data received!\n");
printf("%s", buffer);
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
}
else if((int)proc == 1){
pthread_mutex_lock(&buffer_mutex);
pthread_cond_wait(&buffer_cond, &buffer_mutex);
sprintf(buffer, "Data processed!\n");
printf("%s", buffer);
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
}
else{
sleep(1);
pthread_mutex_lock(&buffer_mutex);
pthread_cond_wait(&buffer_cond, &buffer_mutex);
sprintf(buffer, "Data sent!\n");
printf("%s", buffer);
pthread_mutex_unlock(&buffer_mutex);
}
return(NULL);
}
int main()
{
pthread_t threads[3];
for(int i = 0; i < 3; i++){
pthread_create(&threads[i], NULL, threadFunc, (void *) i);
}
for(int i = 0; i < 3; i++){
pthread_join(threads[i], NULL);
}
return 0;
}
A condition variable is near-useless without a predicate, a conditional state that dictates what has changed. The condition variable is little more than a signaling mechanism to announce that "something" may have changed, but you still need to manage the "what". And that mutex is what protects that "what".
For example:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <pthread.h>
char buffer [100];
int state = 0;
pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER;
void* threadFunc(void *proc)
{
intptr_t iptr = (intptr_t)proc;
pthread_mutex_lock(&buffer_mutex);
switch(iptr)
{
case 0:
{
while (state != 1) // 1 means data available
pthread_cond_wait(&buffer_cond, &buffer_mutex);
// mutex is locked. access predicate data
printf("Data received: %s\n", buffer);
state = 2; // advance state
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_broadcast(&buffer_cond);
}
break;
case 1:
{
while (state != 2)
pthread_cond_wait(&buffer_cond, &buffer_mutex);
// mutex is locked. access predicate data
printf("Data processed: %s\n", buffer);
pthread_mutex_unlock(&buffer_mutex);
}
break;
default:
{
// setup initial send-state
printf("Data sent: %s\n", buffer);
state = 1;
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_broadcast(&buffer_cond);
}
}
return NULL;
}
int main()
{
pthread_t threads[3];
intptr_t i = 0;
strcpy(buffer, "Some message");
for(i = 0; i < 3; i++){
pthread_create(&threads[i], NULL, threadFunc, (void *) i);
}
for( i = 0; i < 3; i++)
pthread_join(threads[i], NULL);
return 0;
}
Output
Data sent: Some message
Data received: Some message
Data processed: Some message
This simply starts up three threads. One (id=0) will wait for the state to become 1, then proceed with its job of announcing what happened, advancing the state, and signaling the condition. The second (id=1) waits for that state, does its job similarly, then simply exits as there is nothing else to to. The third (id=2) is the one that kicks off the process, then silently finishes.
Note that at no time is the predicate data (the state) changed or checked without being under the protection of the mutex on whatever thread is doing said check/changing.
Three timelines with mutex-latch state and which thread owns it will speak volumes in understanding how this works, and I highly advise you get a pencil and paper to assist on that regard.
Best of luck.
Related
I'm investigating the use of PThread.
The main process opens the camera and gets a matrix. Then calls the thread that running job in robot and I want it to be parallel. Basically it works and runs. But still feel unprofessional- because of the bool.
In the code below, this is an example (with fprintf).
I'd love to know how I can fix it without harm parallelism.
In the next code I do not show the call to the robot or camera opening.
There is a feeling that a mutex is needed.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <opencv2/opencv.hpp>
#include <unistd.h> /// for sleep
bool inThread = false;
void *print_message_function( void *ptr );
int main()
{
char mkey = 0;
pthread_t thread1;
char *message1 = "Thread 1";
int iret1;
cv::Mat bgr_image = imread("image.bmp",cv::IMREAD_COLOR);
while(mkey!=27){
if(!inThread){
inThread = true;
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
}
printf("In Main");
imshow("mat", bgr_image);
mkey = cv:: waitKey(5);
}
return 0;
}
void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
sleep(2);
inThread = false;
pthread_exit(NULL);
}
The code works great and does not fall, but it seems unprofessional. Is there a chance that when you update the flag, it will check what is in the flag and fall?
inThread is concurrently read/written so its access shall be protected.
Using a mutex this can for example be done like follows.
Define a global mutex and initialise it:
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
Include errno to be able to do convenient error checking/logging for the pthread_*() calls:
#include <errno.h>
Change this
if(!inThread){
inThread = true;
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
}
to become
errno = pthread_mutex_lock(&m);
if (errno) {
perror("pthread_mutex_lock() failed");
exit(EXIT_FAILURE);
}
if (!inThread) {
inThread = true;
errno = pthread_mutex_unlock(&m);
if (errno) {
perror("pthread_mutex_unlock() failed");
exit(EXIT_FAILURE);
}
...
}
else {
errno = pthread_mutex_unlock(&m);
if (errno) {
perror("pthread_mutex_unlock() failed");
exit(EXIT_FAILURE);
}
}
And change this
inThread = false;
to become
errno = pthread_mutex_lock(&m);
if (errno) {
perror("pthread_mutex_lock() failed");
exit(EXIT_FAILURE);
}
inThread = false;
errno = pthread_mutex_unlock(&m);
if (errno) {
perror("pthread_mutex_unlock() failed");
exit(EXIT_FAILURE);
}
I've never worked with file descriptors and I'm a bit confused about some of this behavior. I'm also fairly new to concurrency and the documentation for these functions is fairly lacking.
My MessageReciever constructor opens a pty. Upon calling the Receive message, as I understand it, the code forks. The master should hit the next conditional and return from the function. I know this is happening because the code in main doesn't block. The child reads in the file descriptor, converts it to a string and saves it in a vector. Currently I'm printing the buffer directly but I also can print the last element in the vector and it acts basically the same. However, when I attempt to access this outside the class, in main, I get nothing. I thought this might be some type of concurrency problem, but I'm not really sure how to address.
CODE
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <stdio.h>
#include <util.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string>
#include <vector>
class MessageReceiver
{
public:
MessageReceiver()
{
openpty(&master, &slave, NULL, NULL, NULL);
}
~MessageReceiver()
{
close(master);
close(slave);
}
void receiveMessage()
{
pid_t pid = fork();
printf("PID = %d\n",pid);
if(pid > 0)
{
fd_set rfds;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
char buf[4097];
ssize_t size;
size_t count = 0;
while (1)
{
if (waitpid(pid, NULL, WNOHANG) == pid)
{
break;
}
FD_ZERO(&rfds);
FD_SET(master, &rfds);
if (select(master + 1, &rfds, NULL, NULL, &tv))
{
size = read(master, buf, 4096);
printf("Buffer = %s", buf);
messageBuffer.push_back(std::string(buf));
buf[size] = '\0';
count += size;
}
}
}
}
std::string getLastMessage()
{
std::string s;
if(messageBuffer.size() > 0)
{
s = messageBuffer.back();
}
else
{
s = "NULL";
}
return s;
}
private:
int master, slave;
std::vector<std::string> messageBuffer;
};
int main()
{
MessageReceiver m;
m.receiveMessage();
std::string lastMessage = m.getLastMessage();
printf("Printing message buffer:\n");
for(;;)
{
if(m.getLastMessage() != lastMessage)
{
printf("Message: %s\n", m.getLastMessage().c_str());
}
}
return 0;
}
Initial output
PID = 8170
PID = 0
Printing message buffer:
Additional output when hello is echoed to the pty
Buffer = hello
I have the test code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_t th_worker, th_worker2;
void * worker2(void *data) {
for(int i = 0; i< 1000000; i++){
printf("thread for worker2----%d\n", i);
usleep(500);
}
}
void * worker(void *data){
pthread_create(&th_worker2, NULL, worker2, data);
for(int i = 0; i< 100; i++){
printf("thread for worker-----%d\n", i);
usleep(500);
}
}
void join(pthread_t _th){
pthread_join(_th, NULL);
}
In main() function, If I call join(the_worker2):
int main() {
char* str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void*) str);
/* problem in here */
join(th_worker2);
return 1;
}
--> Segment Fault error
Else, i call:
join(the_worker);
join(th_worker2);
---> OK
Why have segment fault error in above case?
Thanks for help !!!
If you posted all your code, you have a race condition.
main is synchronized with the start of worker but not worker2.
That is, main is trying to join th_worker2 before worker has had a chance to invoke pthread_create and set up th_worker2 with a valid [non-null] value.
So, th_worker2 will be invalid until the second pthread_create completes, but that's already too late for main. It has already fetched th_worker2, which has a NULL value and main will segfault.
When you add the join for th_worker, it works because it guarantees synchronization and no race condition.
To achieve this guarantee without the join, have main do:
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
while (! th_worker2)
usleep(100);
/* problem in here */
join(th_worker2);
return 1;
}
An even better way to do this is to add an extra variable. With this, the first loop is not needed [but I've left it in]:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int worker_running;
pthread_t th_worker;
int worker2_running;
pthread_t th_worker2;
void *
worker2(void *data)
{
// tell main we're fully functional
worker2_running = 1;
for (int i = 0; i < 1000000; i++) {
printf("thread for worker2----%d\n", i);
usleep(500);
}
return NULL;
}
void *
worker(void *data)
{
// tell main we're fully functional
worker_running = 1;
pthread_create(&th_worker2, NULL, worker2, data);
for (int i = 0; i < 100; i++) {
printf("thread for worker-----%d\n", i);
usleep(500);
}
return NULL;
}
void
join(pthread_t _th)
{
pthread_join(_th, NULL);
}
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
// NOTE: this not necessarily needed as loop below is better
while (! th_worker2)
usleep(100);
// give worker2 enough time to completely start
while (! worker2_running)
usleep(100);
/* problem in here (not anymore!) */
join(th_worker2);
return 1;
}
I need 2 threads: TC and TS, such that they are composed in two main sections each accessing shared data and the threads must to be synchronized. The synchronization should be like this:
The red codes are working with shared data U, but get U can be placed before the dashed rectangle on the TS thread, riht side.
The Xcurrent can be in TC or in TS the tasks, but is a shared hardware with send Ucurrent and get must be right after send was finished.
A dead lock appears and I can't figure out an elegant solution.
Thread TS:
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
#define _USE_MATH_DEFINES
#include <math.h>
#include <windows.h>
#include <pthread.h>
#include <time.h>
// CRLT-C var
static int stop = 0;
// TIMEING vars
__int64 frequencyT, startT, endT = 0;
double baseAngleLast;
double pendulAngleLast;
// THREADING vars
bool startedS = false, Usent = false;
double * Ucmd;
pthread_mutex_t mutexU = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutexBoard = PTHREAD_MUTEX_INITIALIZER;
unsigned int Ulenght = 6;
pthread_cond_t signal_to_read_state = PTHREAD_COND_INITIALIZER;
pthread_cond_t signal_to_read_cmd = PTHREAD_COND_INITIALIZER;
DWORD sleepTime = 30; // in milliseconds
int currentState = 3;
void *sendingCMD(void * )
{
double * U_tmp;
U_tmp = (double*)malloc(sizeof(double)*Ulenght);
startedS = true;
printf("Sin\n");
while (stop == 0)
{
printf("Smu-\n");
//get U
pthread_mutex_lock( &mutexU );
printf("Smu..\n");
pthread_cond_wait(&signal_to_read_cmd, &mutexU);
memcpy(U_tmp,Ucmd,sizeof(double)*Ulenght);
pthread_mutex_unlock( &mutexU );
printf("Smu+\n");
pthread_mutex_lock( &mutexBoard );
for (unsigned int i = 0; i<Ulenght; i++)
{
//send CMD signal
printf("%f ", U_tmp[i]);
if (i == Ulenght -1) printf("\n");
}
Sleep(sleepTime); // miliseconds
currentState = currentState + 1;
pthread_cond_signal(&signal_to_read_state);
pthread_mutex_unlock( &mutexBoard );
printf("Smb\n");
}
printf("Task S terminated. \n");
return (NULL);
}
void *computingU(void *)
{
double * U_tmp;
U_tmp = (double*)malloc(sizeof(double)*Ulenght);
int currentStateTMP =0;
bool fisrtLoop = true;
printf("Uin\n");
while (stop == 0)
{
printf("Umb- \n");
// get current state
pthread_mutex_lock( &mutexBoard );
if (!fisrtLoop)
{
printf("UmbFalse \n");
pthread_cond_wait(&signal_to_read_state, &mutexBoard);
}
else
{
printf("UmbTrue \n");
fisrtLoop=false;
}
currentStateTMP =currentState;
pthread_mutex_unlock( &mutexBoard );
printf("Umb+ \n");
pthread_mutex_lock( &mutexU );
for (unsigned int i=0;i<Ulenght;i++)
{
Ucmd[i] = Ucmd[i]+ (double)currentStateTMP/i;
}
pthread_cond_signal(&signal_to_read_cmd);
pthread_mutex_unlock( &mutexU );
printf("Umu\n");
}
return (NULL);
}
void signal_handler(int signal)
{
stop = 1;
}
int main(int argc, char* argv[])
{
//initializing output buffer to 0[V]
Ucmd= (double*)malloc(sizeof(double)*Ulenght);
for (unsigned int i=0;i<Ulenght;i++)
Ucmd[i] = 0;
//init threads
int rc1, rc2;
pthread_t threadU, threadS;
/* Create independent threads each of which will execute functionC */
if( (rc1=pthread_create( &threadU, NULL, &computingU, NULL)) ) {
printf("ThreadU creation failed: %d\n", rc1);
}
if( (rc2=pthread_create( &threadS, NULL, &sendingCMD, NULL)) )
{
printf("ThreadS creation failed: %d\n", rc2);
}
while (stop == 0);
printf("Main terminated, closing board in 10ms. \n");
Sleep(10);
return 0;
}
The blocking appears at:
TC at pthread_cond_wait(&signal_to_read_state, &mutexBoard);
TS at pthread_cond_wait(&signal_to_read_cmd, &mutexU);
btw why dose not recognize stackoverflow the code segment I pasted above in case i copy paste from a VS2010?
I am experimenting with pthreads. I am trying to create three threads and have them operate on a global char buffer. I am using mutex lock and unlock for their critical sections. The program flow should go: Main spawns three threads. Thread one locks, initializes the buffer, prints it out, signals thread two, and unlocks. Thread two enters its critical section operates on the buffer and signals thread three, etc. It seems to work, sometimes. Other times, it seems like it is getting suck in a spin lock. Any help in the right direction would be great. Thanks.
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
using namespace std;
const int num_threads = 3;
char buffer[100];
pthread_mutex_t buffer_mutex = pthread_mutex_initializer;
pthread_cond_t buffer_cond = pthread_cond_initializer;
void* firstthreadfunc(void* proc) {
string a = "data received";
pthread_mutex_lock(&buffer_mutex);
sleep(1);
cout<<"threadone"<<endl;
for(int i = 0;i<14;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
void* secondthreadfunc(void* proc) {
string a = "data processed";
pthread_mutex_lock(&buffer_mutex);
pthread_cond_wait(&buffer_cond, &buffer_mutex);
sleep(1);
cout<<"threadtwo"<<endl;
for(int i = 0; i<15 ;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
void* thirdthreadfunc(void* proc) {
string a = "data sent";
pthread_mutex_lock(&buffer_mutex);
pthread_cond_wait(&buffer_cond, &buffer_mutex);
sleep(1);
cout<<"thread three"<<endl;
for(int i = 0;i<9;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
int main() {
pthread_t p_threadone, p_threadtwo, p_threadthree;;
pthread_attr_t attr;
pthread_attr_init(&attr);
for(int i = 0;i<100;i++){
buffer[i] = 'a';
}
//create threads
cout<<"creating threads"<<endl;
pthread_create(&p_threadone, &attr, firstthreadfunc, null);
pthread_create(&p_threadtwo, &attr, secondthreadfunc, null);
pthread_create(&p_threadthree, &attr, thirdthreadfunc, null);
//terminate threads
pthread_join(p_threadone,null);
pthread_join(p_threadtwo,null);
pthread_join(p_threadthree,null);
return 0;
}
Thanks WhozCraig and Tony, your answers resolved the issue. I understand what I was doing wrong.
First, where you're stuck. The following line in either thread2 or thread3 is the sticking point:
pthread_cond_wait(&buffer_cond, &buffer_mutex);
And by now you're asking, "Why?" Because your mistaking a condition variable as a state; not a signaling mechanism. Condition variables are intended to be used to signal interested waiters of change in state of something else: the predicate. You have none. Consider the following modified version of your code.
This uses two predicate values (I advise you stick with one per condvar until you become more comfortable with them; start simple), protecting them with the same mutex and signaling their change with the same condition variable. The important thing to note is that we don't wait on the condition variable until we know the predicate we're waiting for is not ready yet. And since we have the mutex locked, we can safely do check that predicate:
#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>
using namespace std;
const int NUM_THREADS = 3;
char buffer[100];
bool bDataReady = false;
bool bDataWaiting = false;
pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER;
void* firstThreadFunc(void* proc)
{
string a = "Data Received";
pthread_mutex_lock(&buffer_mutex);
cout<<"ThreadOne"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataReady = true;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
void* secondThreadFunc(void* proc)
{
string a = "Data Processed";
pthread_mutex_lock(&buffer_mutex);
while (!bDataReady)
pthread_cond_wait(&buffer_cond, &buffer_mutex);
cout<<"ThreadTwo"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataReady = false;
bDataWaiting = true;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
void* thirdThreadFunc(void* proc)
{
string a = "Data Sent";
pthread_mutex_lock(&buffer_mutex);
while (!bDataWaiting)
pthread_cond_wait(&buffer_cond, &buffer_mutex);
cout<<"Thread Three"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataWaiting = false;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
int main() {
pthread_t p_threadOne, p_threadTwo, p_threadThree;;
pthread_attr_t attr;
pthread_attr_init(&attr);
for(int i = 0;i<100;i++){
buffer[i] = 'a';
}
//create Threads
cout<<"creating threads"<<endl;
pthread_create(&p_threadOne, &attr, firstThreadFunc, NULL);
pthread_create(&p_threadTwo, &attr, secondThreadFunc, NULL);
pthread_create(&p_threadThree, &attr, thirdThreadFunc, NULL);
//terminate Threads
pthread_join(p_threadOne,NULL);
pthread_join(p_threadTwo,NULL);
pthread_join(p_threadThree,NULL);
return 0;
}
Output
creating threads
ThreadOne
Data Received
ThreadTwo
Data Processed
Thread Three
Data Sent