#include<stdio.h>
#include<pthread.h>
#define nThreads 5
pthread_mutex_t lock;
void *start(void *param) {
pthread_mutex_lock(&lock);
while (true)
{
//do certain things , mutex to avoid critical section problem
int * number = (int *) param;
cout<<*number;
}
pthread_mutex_unlock(&lock);
}
int main()
{
pthread_mutex_init(&lock, NULL);
pthread_t tid[nThreads];
int i = 0;
for(i = 0; i < nThreads; i++) pthread_create(&tid[i], NULL, start, (void *) &i);
for(i = 0; i < nThreads; i++) pthread_join(tid[i], NULL);
pthread_mutex_destroy(&lock);
return 0;
}
my question is whether all the threads are looping infinitely or only the first thread is looping. and if only one thread is looping, how to make all threads loop infinitely and should mutex be inside the while loop or outside :S !!
thanks in advance.
If the mutex is outside the loop as you've shown, then only one thread can enter that loop. If that loop runs forever (as while (true) will do if there's no break statement inside), then only one thread will actually get to loop and the rest will be locked out.
Move the mutex around just the code that you need to protect. If you want all the threads looping in parallel, taking turns accessing a common structure, move the mutex inside the loop.
In this case only 1 thread is in loop , also this will be the first thread to enter since that will never unlock mutex no other thread will enter ie, all other thread will wait indefinitely. I think what you want is this:
while (true)
{
pthread_mutex_lock(&lock);
//do certain things , mutex to avoid critical section problem
int * number = (int *) param;
cout<<*number;
pthread_mutex_unlock(&lock);
}
Related
I have some class objects and want to hand them over to several threads. The number of threads is given by the command line.
When I write it the following way, it works fine:
thread t1(thread(thread(tasks[0], parts[0])));
thread t2(thread(thread(tasks[1], parts[1])));
thread t3(thread(thread(tasks[2], parts[2])));
thread t4(thread(thread(tasks[3], parts[3])));
t1.join();
t2.join();
t3.join();
t4.join();
But as I mentioned, the number of threads shall be given by the command line, so it must be more dynamic. I tried the following code, which doesn't work, and I have no idea what is wrong with it:
for(size_t i=0; i < threads.size(); i++) {
threads.push_back(thread(tasks[i], parts[i]));
}
for(auto &t : threads) {
t.join();
}
I hope someone has an idea on how to correct it.
In this statement:
thread t1(thread(thread(tasks[0], parts[0])));
You don't need to move a thread into another thread and then move that into another thread. Just pass your task parameters directly to t1's constructor:
thread t1(tasks[0], parts[0]);
Same with t2, t3, and t4.
As for your loop:
for(size_t i=0; i < threads.size(); i++) {
threads.push_back(thread(tasks[i], parts[i]));
}
Assuming you are using std::vector<std::thread> threads, then your loop is populating threads wrong. At best, the loop simply won't do anything at all if threads is initially empty, because i < threads.size() will be false when size()==0. At worst, if threads is not initially empty then the loop will run and continuously increase threads.size() with each call to threads.push_back(), causing an endless loop because i < threads.size() will never be false, thus pushing more and more threads into threads until memory blows up.
Try something more like this instead:
size_t numThreads = ...; // taken from cmd line...
std::vector<std::thread> threads(numThreads);
for(size_t i = 0; i < numThreads; i++) {
threads[i] = std::thread(tasks[i], parts[i]);
}
for(auto &t : threads) {
t.join();
}
Or this:
size_t numThreads = ...; // taken from cmd line...
std::vector<std::thread> threads;
threads.reserve(numThreads);
for(size_t i = 0; i < numThreads; i++) {
threads.emplace_back(tasks[i], parts[i]);
}
for(auto &t : threads) {
t.join();
}
Threads are not copyable; try this:
threads.emplace_back(std::thread(task));
Emplace back thread on vector
Problem: Let's say we have n threads where each thread receives a random unique number between 1 and n. And we want the threads to print the numbers in sorted order.
Trivial Solution (using n semaphore/mutex): We can use n mutex locks (or similarly semaphores) where thread i waits to acquire mutex lock number i and unlocks number i + 1. Also, thread 1 has no wait.
However, I'm wondering if it's possible to simulate a similar logic using a single semaphore (of type sem_t) to implement the following logic: (i is a number between 1 to n inclusive)
Thread with number i as input, waits to acquire a count of (i-1) on the semaphore, and after
printing, releases a count of i. Needless to say, thread one does not
wait.
I know that unlike Java, sem_t does not support arbitrary increase/decrease in the semaphore value. Moreover, writing a for loop to do (i-1) wait and i release won't work because of asynchrony.
I've been looking for the answer for so long but couldn't find any. Is this possible in plain C? If not, is it possible in C++ using only one variable or semaphore? Overall, what is the least wasteful way to do this with ONE semaphore.
Please feel free to edit the question since I'm new to multi-threaded programming.
You can do this with a condition_variable in C++, which is equivalent to a pthread_cond_t with the pthreads library in C.
What you want to share between threads is a pointer to a condition_variable, number, and a mutex to guard access to the number.
struct GlobalData
{
std::condition_variable cv;
int currentValue;
std::mutex mut;
};
Each thread simply invokes a function that waits for its number to be set:
void WaitForMyNumber(std::shared_ptr<GlobalData> gd, int number)
{
std::unique_lock<std::mutex> lock(gd->mut);
while (gd->currentValue != number)
{
gd->cv.wait(lock);
}
std::cout << number << std::endl;
gd->currentValue++;
gd->cv.notify_all(); // notify all other threads that it can wake up and check
}
And then a program to test it all out. This one uses 10 threads. You can modify it to use more and then have your own randomization algorithm of the numbers list.
int main()
{
int numbers[10] = { 9, 1, 0, 7, 5, 3, 2, 8, 6, 4 };
std::shared_ptr<GlobalData> gd = std::make_shared<GlobalData>();
// gd->number is initialized to 0.
std::thread threads[10];
for (int i = 0; i < 10; i++)
{
int num = numbers[i];
auto fn = [gd, num] {WaitForMyNumber(gd, num); };
threads[i] = std::move(std::thread(fn));
}
// wait for all the threads to finish
for (int i = 0; i < 10; i++)
{
threads[i].join();
}
return 0;
}
All of the above is in C++. But it would be easy to transpose the above solution to C using pthreads. But I'll leave that as an exercise for the OP.
I'm not sure if this satisfies your "one semaphore requirement". The mutex technically has a semaphore. Not sure if the condition_variable itself has a semaphore for its implementation.
Thats a good question although, I fear you might have a XY problem since I can not imagine a good reason for your problem scenario. Never the less, after 1-2 minutes I came up with 2 solutions with pros and cons, but I think one is perfect for you:
A. When your threads are almost done the same time and or need their print ASAP you could use a shared std::atomic<T> with T=unsigned,int,size_t,uint32_t what ever you like, or any of the integer atomics in the C standard library when using C, initialise it with 0, and now every thread i busy waits until its value is i-1. If so, it prints and then adds 1 on the atomic. Of course since of the busy wait, you will have much CPU load when thread are waiting long, and slow down, when many are waiting. But you get your print ASAP
B. You just store your result of thread i in a container, maybe along with its index, since I guess you want more to just print i, and after all threads are finished or periodically, sort this container and then print it.
A.:
#include <iostream>
#include <atomic>
#include <thread>
#include <vector>
#include <functional>
void thread_function(unsigned i, std::atomic<unsigned>& atomic) {
while (atomic < i - 1) {}
std::cout << i << " ";
atomic += 1;
}
int main() {
std::atomic<unsigned> atomic = 0;
std::vector<std::thread> threads;
for (auto i : {3,1,2}) {
threads.push_back(std::thread(thread_function, i, std::ref(atomic)));
}
for (auto& t : threads) {
t.join();
}
std::cout << "\n";
}
Works also in C, just use the atomics there.
The following code uses pthread_cond_t and works in C.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define n 100
int counter = 0;
int used[n];
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void foo(void *given_number){
int number = (int)given_number;
pthread_mutex_lock(&mutex);
while(counter != number){
pthread_cond_wait(&cond, &mutex);
}
printf("%d\n", number);
counter++;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
int get_random_number(){
while(1){
int x = rand()%n;
if(!used[x]){
used[x] = 1;
return x;
}
}
}
int main(){
pthread_t threads[n];
for(int i = 0; i < n; i++){
int num = get_random_number();
pthread_create(&threads[i], NULL, foo, (void *)num);
}
for(int i = 0; i < n; i++){
pthread_join(threads[i], NULL);
}
return 0;
}
I have an array. And I need to fill it with two threads each value consequently, using omp_set_lock, and omp_unset_lock. First thread should write first value, then second array should write second value etc. I have no idea how to do that, because, in openmp you cant't explicitly make one thread wait for another. Have any ideas?
Why not try the omp_set_lock/omp_unset_lock functions?
omp_lock_t lock;
omp_init_lock(&lock);
#pragma omp parallel for
bool thread1 = true;
for (int i = 0; i < arr.size(); ++i) {
omp_set_lock(&lock);
if (thread1 == true) {
arr[i] = fromThread1();
thread1 = false;
} else {
arr[i] = fromThread2();
thread1 = true;
}
omp_unset_lock(&lock);
}
I'm trying to write some code that creates threads that can modify different parts of memory concurrently. I read that a mutex is usually used to lock code, but I'm not sure if I can use that in my situation. Example:
using namespace std;
mutex m;
void func(vector<vector<int> > &a, int b)
{
lock_guard<mutex> lk(m);
for (int i = 0; i < 10E6; i++) { a[b].push_back(1); }
}
int main()
{
vector<thread> threads;
vector<vector<int> > ints(4);
for (int i = 0; i < 10; i++)
{
threads.push_back(thread (func, ref(ints), i % 4));
}
for (int i = 0; i < 10; i++) { threads[i].join(); }
return 0;
}
Currently, the mutex just locks the code inside func, so (I believe) every thread just has to wait until the previous is finished.
I'm trying to get the program to edit the 4 vectors of ints at the same time, but that does realize it has to wait until some other thread is done editing one of those vectors before starting the next.
I think you want the following: (one std::mutex by std::vector<int>)
std::mutex m[4];
void func(std::vector<std::vector<int> > &a, int index)
{
std::lock_guard<std::mutex> lock(m[index]);
for (int i = 0; i < 10E6; i++) {
a[index].push_back(1);
}
}
Have you considered using a semaphore instead of a mutex?
The following questions might help you:
Semaphore Vs Mutex
When should we use mutex and when should we use semaphore
try:
void func(vector<vector<int> > &a, int b)
{
for (int i=0; i<10E6; i++) {
lock_guard<mutex> lk(m);
a[b].push_back(1);
}
}
You only need to lock your mutex while accessing the shared object (a). The way you implemented func means that one thread must finish running the entire loop before the next can start running.
There is a program I am working on that, after I launch it, works for some time and then stalls. Here is a simplified version of the program:
#include <cstdlib>
#include <iostream>
#include <pthread.h>
pthread_t* thread_handles;
pthread_mutex_t mutex;
pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
int thread_count;
const int some_count = 77;
const int numb_count = 5;
int countR = 0;
//Initialize threads
void InitTh(char* arg[]){
/* Get number of threads */
thread_count = strtol(arg[1], NULL, 10);
/*Allocate space for threads*/
thread_handles =(pthread_t*) malloc (thread_count*sizeof(pthread_t));
}
//Terminate threads
void TermTh(){
for(long thread = 0; thread < thread_count; thread++)
pthread_join(thread_handles[thread], NULL);
free(thread_handles);
}
void* DO_WORK(void* replica) {
/*Does something*/
pthread_mutex_lock(&mutex);
countR++;
if (countR == numb_count) pthread_cond_broadcast(&cond_var);
pthread_mutex_unlock(&mutex);
}
//Some function
void FUNCTION(){
pthread_mutex_init(&mutex, NULL);
for(int k = 0; k < some_count; k++){
for(int j = 0; j < numb_count; j++){
long thread = (long) j % thread_count;
pthread_create(&thread_handles[thread], NULL, DO_WORK, (void *)j);;
}
/*Wait for threads to finish their jobs*/
pthread_mutex_lock(&mutex);
if (countR < numb_count) while(pthread_cond_wait(&cond_var,&mutex) != 0);
countR = 0;
pthread_mutex_unlock(&mutex);
/*Does more work*/
}
pthread_cond_destroy(&cond_var);
pthread_mutex_destroy(&mutex);
}
int main(int argc, char* argv[]) {
/*Initialize threads*/
InitTh(argv);
/*Do some work*/
FUNCTION();
/*Treminate threads*/
TermTh();
return 0;
}
When some_count, (in my particular case,) is less than 76, the program works fine, but if I specify a larger value the program, as mentioned earlier, works for some time and then stalls. Maybe somebody can point out what I am doing wrong?
In
long thread = (long) j % thread_count;
pthread_create(&thread_handles[thread], NULL, DO_WORK, (void *)j);;
you can "override" initialized thread handles, depending on your actual thread count parameter.
I think you should init the thread number to numb_count rather then argv
then replace
long thread = (long) j % thread_count;
with
long thread = (long) j;
won't sure it fix it, but it's needed anyway...
Moreover, it's not about the number 76 or 77, you have a race condition in the thread use.
lets say that one of you threads got to the point in "DO_WORK" when he unlock the mutex but he still didn't returned from this function (meaning the thread is still running...). then you may try to create the same thread in the next iteration using:
pthread_create(&thread_handles[thread], NULL, DO_WORK, (void *)j);
fixing, change:
pthread_mutex_lock(&mutex);
if (countR < numb_count) while(pthread_cond_wait(&cond_var,&mutex) != 0);
countR = 0;
pthread_mutex_unlock(&mutex);
to:
pthread_mutex_lock(&mutex);
if (countR < numb_count) while(pthread_cond_wait(&cond_var,&mutex) != 0);
countR = 0;
for(long thread = 0; thread < numb_count; thread++)
pthread_join(thread_handles[thread], NULL);
pthread_mutex_unlock(&mutex);
You could try to analyze it using helgrind.
Install valgrind, then launch valgrind --tool=helgrind yourproject and see what helgrind spits out
You are neither initializing your mutex correctly (not causing the error here), nor storing the threads you create correctly. Try this:
for(int count = 0; count < thread_count; ++count) {
pthread_create(&thread_handles[count], NULL, DO_WORK, (void *)(count % numb_count));
}