I have created a simple c++ program which is used for logging. I am creating threads in a for loop which runs 1000 times in test.cpp
which is the driver file. pthread_create
calls the print function in tt.cpp
which writes the input parameter ie i, in file.txt
. I wish to synchronize the threads.
I have tried using pthread_join
which synchronized the threads but I wish to synchronize the threads without using join.
I know that if a thread is locked, a lot of threads will be waiting until it gets unlocked and after that thread is unlocked, any one of the waiting threads will lock the function. So, I tried to use a static integer variable in tt.cpp
and tried to compare it with the input parameter so that I can use pthread_cond_wait
and pthread_wait_signal
but I got segmentation fault on comparing.
/* if(j == *((int *)input)))
This comparison gave me a segmentation fault */
-------------------------test.cpp---------------------------------
#include "thr.h"
pthread_mutex_t loc;
FILE *thePrintFile = NULL;
int main()
{
pthread_mutex_init(&loc,NULL);
pthread_t p;
thePrintFile = fopen("file.txt","r+");
for(int i =0; i<1000;i++)
{
pthread_create(&p,NULL,print,(void *)i);
}
for(int k = 0; k<100000;k++);
/* i have used it to ensure that the main thread
doesn't exit before the pthreads finish writing */
return 0;
}
------------------------tt.cpp------------------------------------
#include "thr.h"
extern pthread_mutex_t loc;
extern FILE *thePrintFile;
void* print(void *input)
{
if(pthread_mutex_trylock(&loc) == 0)
{
fprintf(thePrintFile,"%s%d\n",(int *)input);
fflush(thePrintFile);
pthread_mutex_unlock(&loc);
}
}
-----------------------------thr.h--------------------------------
#ifndef THR_H_INCLUDED
#define THR_H_INCLUDED
void* print(void *input);
#endif
Given below is a part of file.txt .
1
5
9
10
11
12
13
14
15
16
18
19
20
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
21
201
202
To synchronize the threads properly, you need to use a synchronization device such as a condition variable . Since you are using C++, you are much better off using its built-in threads rather than the raw pthread API.
For example, this code synchronizes 1000 threads so that each prints its own ID using a condition variable and mutex pair to ensure that the IDs are printed in order, as tracked by a separate variable shared by all. It is not very efficient because all threads fight for the same mutex, but it works correctly. It could be made more efficient by creating a condition variable for each thread, but doing it correctly would require a better understanding of your actual use case.
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
#include <vector>
static std::mutex mutex;
static std::condition_variable condvar;
static int whos_next;
static void work(int id) {
std::unique_lock<std::mutex> lock{mutex};
// wait for our turn
condvar.wait(lock, [=]() { return whos_next == id; });
// it's our turn now - print our thread ID
std::cout << id << '\n';
++whos_next;
condvar.notify_all(); // notify the next thread to run
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 1000; i++)
threads.push_back(std::thread([=]() { work(i); }));
for (auto &t: threads)
t.join();
}
Note that the above code's use of join
is not to synchronize the threads with each other (they synchronize among themselves using the mutex/condition), but for its intended purpose: to wait for the threads to finish before exiting main()
. C++ even requires that you do that before destructing the std::thread
object, so removing the join results in program termination. You can easily prove that the threads don't rely on join
for synchronization, eg by inserting a sleep before joins, or by joining them in reverse order.
I see multiple problems in your code.
Then let's look at the comparison you try to make:
if(j == *((int *)input)))
j is obviously int. input is void *. At the basis input was int. Because casting int to void * is not guaranteed to be safe, casting it back is not safe either. Imagine that int is 64bits and a pointer is 32bit. If you cast your int to void * you lose 32 bits. Then you cast from 32bit to 64bit, so you add 32bit of 0's. Obviously that is going to give problems.
Consider using C++11, that will greatly improve your code. https://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.