I have written this Producer/Consumer Problem solution. It seems to be working, other than the infinite loop. I was under the impression that pthread_exit(NULL); would make it stop, but honestly, I've become lost and confused. Could someone point me in the right direction of how to stop the loop?
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<iostream>
#include<semaphore.h>
#define BUFFSIZE 10
using namespace std;
int buffer[BUFFSIZE];
int size; //current buffer size
int n = 0, m = 0;
pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t Available;
sem_t Buffer; //indicates if buffer is full
//----------------------------------------------------------------//
void *Consumers(void *argument)
{
int con_id = *((int *) argument);
while(1)
{
if(size == 0)
{
cout << "Queue is empty." << endl;
}
sem_wait(&Available);
pthread_mutex_lock(&Mutex);
size--;
cout << "Con " << con_id << ": Product removed from buffer" << endl;
//for(int i = 0; i < size; i++)
//{
// cout << Buffer[i] << " ";
//}
cout << endl;
pthread_mutex_unlock(&Mutex);
sem_post(&Buffer);
}
return(NULL);
}
//----------------------------------------------------------------//
void *Producers(void *argument)
{
int item = 8;
int pro_id = *((int *) argument);
while(1)
{
sem_wait(&Buffer);
pthread_mutex_lock(&Mutex);
//Buffer[size] = item;
cout << "Item added" << endl;
size++;
pthread_mutex_unlock(&Mutex);
sem_post(&Available);
}
return(NULL);
}
//----------------------------------------------------------------//
int main()
{
cout << "Enter number of producers: " << endl;
scanf("%d", &n);
cout << "Enter number of consumers: " << endl;
scanf("%d", &m);
//get number of producers(int n), and consumers(int m)
sem_init(&Available, 0, 0);
sem_init(&Buffer, 0, BUFFSIZE);
pthread_t *con = new pthread_t[m];
int *thread_args_c = new int[m];
for(int i = 0; i < n; i++)
{
thread_args_c[i] = i;
pthread_create(&con[i], NULL, Consumers, (void*) &i);
}
pthread_t *pro = new pthread_t[n];
int *thread_args_p = new int[n];
for(int i = 0; i < n; i++)
{
thread_args_p[i] = i;
pthread_create(&pro[i], NULL, Producers, (void*) &i);
pthread_join(con[i], NULL);
}
pthread_exit(NULL);
}
Not sure what you are expecting. pthread_exit appears in the end of the main (and completely not needed there, since main is exiting anyways), but your enless loops inside thread will never let main reach this point (since you are joining the consumers thread).
Also, your creation and joining model makes litle sense - what's the point of joining consumer thread after you've created a producer?
And last, but not the lease, you fail to join producer thread.
The loops will not stop because there is no logic in the code to actually exit the loop.
The process is stuck because pthread_join suspends the calling thread till the target exits. See documentation for pthread_join
If you don't care about actually terminating the threads and returning to the main thread, just remove the call to pthread_join. The process should terminate because the main thread exited.
To actually properly terminate the loops, you need to set an internal or external trigger. You could internally have the loops exit after a set number of iterations. For this, you will do while(x<=y) instead of while(1).
You could also make it more complicated and have the main thread signal the other threads externally that it wants the other threads to shut down. You can have the main thread set a (volatile) boolean when you are ready to exit and have the other threads break the loop based on it. If you care about the Atomicity of the exit, you will need to protect the boolean with a lock.
Related
I want a thread to run infinity times in order to execute the task described on do_work() function that it receives. However, the function is only called on the pthread_create() subroutine.
I've tried to implement the sched_yield() and the pthread_join() routines on a while loop. But it didn't work yet.
Is there any routine in which I can call the existing thread again?
int main (int argc, char ** argv) {
int period;
int priority;
int load;
char schedule[15];
period = atoi(argv[1]);
priority = atoi(argv[2]);
load = atoi(argv[3]);
strncpy(schedule,argv[4],100);
std::cout << " period : " << period <<"\n priority : "<< priority << "\n load : "<< load << "\n schedule : " << schedule <<std::endl;
struct sched_param param;
pthread_t thread;
int rc;
sched_setscheduler (0, SCHED_FIFO , ¶m);
std::cout << "main() : creating thread " << std::endl;
rc = pthread_create(&thread, NULL, do_work, (void*)load);
if (rc) {
std::cout << "Error:unable to create thread " << rc << std::endl;
exit(-1);
}
int i=0;
struct sigaction action;
struct itimerval timer;
while(i<10000){
pthread_join(thread, NULL);
sched_yield();
i++;
}
pthread_exit(NULL);
}
You do not call a thread, you create a thread. By doing that, you specify a start_routine which will be called 'in' the new thread.
If you want to call repeatedly a function in a loop, then you can do the following in your start_routine:
void* start_routine(void *arg) {
while (active) { // active: atomic global boolean value
do_work();
}
// if no longer active,
// there could be an option to wait to become active again,
// or exit the thread
pthread_exit(NULL);
}
pthread_join() is only called, if you want to join a thread with other thread(s). pthread_join() waits until the target thread has terminated. By joining the thread, all resources are given back to the system (cleanup).
Just wanted to show you the code I implemented.
I was not sure about the meaning of Threads when I made this question and you helped me to understand that I cannot access the function on a thread multiple times, but I have to create it on each use.
My main objective was to find a way of calling the do_work() function on the reception of the signal SIGALRM. Thus, I just assumed the do_wordk() to be my Thread and used a sigaction struct to control the arrival of the signal.
If you guys want to test the code, it returns the execution time of the do_work() function and a message if the deadline set on your period was lost. The purpose of this work was to make an analogy with periodic threads.
To compile:
g++ teste.cpp -o exe -lrt
To run:
sudo taskset -c 0 ./exe 300 1 100000 F
sudo taskset -c 0 ./exe Period Priority Work_Load Scheduller_Policy
#include<signal.h>
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<sys/time.h>
#include<iostream>
#include<string>
#include<string.h>
long load=1;
void deadline();
void do_work();
void wakeup(int j){
struct itimerval aux;
int t1, t2;
getitimer( ITIMER_REAL, &aux); //Get initial resume time
t1 = aux.it_value.tv_usec;
//std::cout << "Hello World! Thread working |Resume Time : " <<t1<< std::endl;
do_work();
getitimer( ITIMER_REAL, &aux);
t2 = aux.it_value.tv_usec; //Get Final resume time
std::cout << "Execution time (usec): " <<t1 - t2<< std::endl;
if (t2==0){
deadline();
}
return;
}
void do_work(){
for ( int i = 0; i < load * 1000; i++) {
/* do nothing , keep counting */
}
}
void deadline() {
std::cout << "Lost deadline!" << std::endl;
}
int main (int argc, char ** argv) {
int i;
int period;
int priority;
char scheduler[5];
period = atoi(argv[1])*1000;
priority = atoi(argv[2]);
load = atoi(argv[3]);
strcpy(scheduler, argv[4]);
std::cout << " period : " << period <<"\n priority : "<< priority << "\n load : "<< load << "\n scheduler : " << scheduler <<std::endl;
struct sched_param param;
param.sched_priority = priority;
if (scheduler[0]=='F'){
int r = sched_setscheduler (0, SCHED_FIFO , ¶m);
if(r==-1){ perror("scheduller"); return 1;}
std::cout <<"FIFO scheduller: "<<r<<std::endl;
}else{
int r = sched_setscheduler (0, SCHED_RR , ¶m);
if(r==-1){ perror("scheduller"); return 1;}
std::cout <<"RR scheduller: "<<r<<std::endl;
}
struct itimerval val;
struct sigaction action;
sigset_t mask;
sigemptyset(&action.sa_mask);
action.sa_handler = wakeup;
action.sa_flags=SA_RESTART;
if(sigaction(SIGALRM, &action, 0)==-1){
perror("sigaction");
return 1;
}
val.it_interval.tv_sec=0;
val.it_interval.tv_usec=period;
val.it_value.tv_sec=0;
val.it_value.tv_usec=period;
if(setitimer(ITIMER_REAL, &val, 0)==-1){
perror("setitimer");
return 1;
}
if(sigwait( &mask, &i)==-1){
perror("sigwait");
}
return 0;
}
Finally, I am really grateful for your patience in understanding my problem. This is my first question on this community and I hope I'll improve them over time. Thank you all for your answers and the effort on helping me.
I am implementing a producer consumer project in c++, and when I run the program, the same consumer grabs almost all of the work, without letting any of the other consumer threads grab any. Sometimes, other threads do get some work, but then that other thread takes control for a while. for example, TID 10 could grab almost all of the work, but then all of a sudden TID 12 would grab it, with no other consumer threads getting work in between.
Any idea why other threads wouldn't have a chance to grab work?
#include <thread>
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <deque>
#include <csignal>
#include <unistd.h>
using namespace std;
int max_queue_size = 100;
int num_producers = 5;
int num_consumers = 7;
int num_operations = 40;
int operations_created = 0;
thread_local int operations_created_by_this_thread = 0;
int operations_consumed = 0;
thread_local int operations_consumed_by_this_thread = 0;
struct thread_stuff {
int a;
int b;
int operand_num;
char operand;
};
char operands[] = {'+', '-', '/', '*'};
deque<thread_stuff> q;
bool finished = false;
condition_variable cv;
mutex queue_mutex;
void producer(int n) {
while (operations_created_by_this_thread < num_operations) {
int oper_num = rand() % 4;
thread_stuff equation;
equation.a = rand();
equation.b = rand();
equation.operand_num = oper_num;
equation.operand = operands[oper_num];
while ((operations_created - operations_consumed) >= max_queue_size) {
// don't do anything until it has space available
}
{
lock_guard<mutex> lk(queue_mutex);
q.push_back(equation);
operations_created++;
}
cv.notify_all();
operations_created_by_this_thread++;
this_thread::__sleep_for(chrono::seconds(rand() % 2), chrono::nanoseconds(0));
}
{
lock_guard<mutex> lk(queue_mutex);
if(operations_created == num_operations * num_producers){
finished = true;
}
}
cv.notify_all();
}
void consumer() {
while (true) {
unique_lock<mutex> lk(queue_mutex);
cv.wait(lk, [] { return finished || !q.empty(); });
if(!q.empty()) {
thread_stuff data = q.front();
q.pop_front();
operations_consumed++;
operations_consumed_by_this_thread++;
int ans = 0;
switch (data.operand_num) {
case 0:
ans = data.a + data.b;
break;
case 1:
ans = data.a - data.b;
break;
case 2:
ans = data.a / data.b;
break;
case 3:
ans = data.a * data.b;
break;
}
cout << "Operation " << operations_consumed << " processed by PID " << getpid()
<< " TID " << this_thread::get_id() << ": "
<< data.a << " " << data.operand << " " << data.b << " = " << ans << " queue size: "
<< (operations_created - operations_consumed) << endl;
}
this_thread::yield();
if (finished) break;
}
}
void usr1_handler(int signal) {
cout << "Status: Produced " << operations_created << " operations and "
<< (operations_created - operations_consumed) << " operations are in the queue" << endl;
}
void usr2_handler(int signal) {
cout << "Status: Consumed " << operations_consumed << " operations and "
<< (operations_created - operations_consumed) << " operations are in the queue" << endl;
}
int main(int argc, char *argv[]) {
if (argc < 5) {
cout << "Invalid number of parameters passed in" << endl;
exit(1);
}
max_queue_size = atoi(argv[1]);
num_operations = atoi(argv[2]);
num_producers = atoi(argv[3]);
num_consumers = atoi(argv[4]);
// signal(SIGUSR1, usr1_handler);
// signal(SIGUSR2, usr2_handler);
thread producers[num_producers];
thread consumers[num_consumers];
for (int i = 0; i < num_producers; i++) {
producers[i] = thread(producer, num_operations);
}
for (int i = 0; i < num_consumers; i++) {
consumers[i] = thread(consumer);
}
for (int i = 0; i < num_producers; i++) {
producers[i].join();
}
for (int i = 0; i < num_consumers; i++) {
consumers[i].join();
}
cout << "finished!" << endl;
}
You're holding the mutex the whole time--including yield()-ing while holding the mutex.
Scope the unique_lock like you do in your producer's code, popping from the queue and incrementing the counter atomically.
I see that you have a max queue size. You need a 2nd condition for the producer to wait on if the queue is full, and the consumer will signal this condition as it consumes items.
Any idea why other threads wouldn't have a chance to grab work?
This poll is troubling:
while ((operations_created - operations_consumed) >= max_queue_size)
{
// don't do anything until it has space available
}
You might try a minimal delay in the loop ... this is a 'bad neighbor', and can 'consume' a core.
There are few issues with your code:
Using Normal Variables for Inter-Thread Communication
Here is an example:
int operations_created = 0;
int operations_consumed = 0;
void producer(int n) {
[...]
while ((operations_created - operations_consumed) >= max_queue_size) { }
and later
void consumer() {
[...]
operations_consumed++;
This will work only on x86 architectures without optimizations, i.e. -O0. Once we try to enable optimizations, the compiler will optimize the while loop to:
void producer(int n) {
[...]
if ((operations_created - operations_consumed) >= max_queue_size) {
while (true) { }
}
So, your program simply hang here. You can check this on Compiler Explorer.
mov eax, DWORD PTR operations_created[rip]
sub eax, DWORD PTR operations_consumed[rip]
cmp eax, DWORD PTR max_queue_size[rip]
jl .L19 // here is the if before the loop
.L20:
jmp .L20 // here is the empty loop
.L19:
Why is this happening? From the single-thread program point of view, while (condition) { operators } is exact equivalent to if (condition) while (true) { operators } if operators do not change the condition.
To fix the issue, we should use std::atomic<int> instead of simple int. Those are designed for inter-thread communication and so compiler will avoid such optimizations and generate the correct assembly.
Consumer Locks The Mutex while yield()
Have a look at this snippet:
void consumer() {
while (true) {
unique_lock<mutex> lk(queue_mutex);
[...]
this_thread::yield();
[...]
}
Basically this mean that consumer does the yield() holding the lock. Since only one consumer can hold a lock at a time (mutex stands for mutual exclusion), that explains why other consumers cannot consume the work.
To fix this issue, we should unlock the queue_mutex before the yield(), i.e.:
void consumer() {
while (true) {
{
unique_lock<mutex> lk(queue_mutex);
[...]
}
this_thread::yield();
[...]
}
This still does not guarantee that only one thread will do most of the tasks. When we do notify_all() in producer, all threads get woke up, but only one will lock the mutex. Since the work we schedule is tiny, by the time producer calls notify_all() our thread will finish the work, done the yield() and will be ready for the next work.
So why this thread locks the mutex, but not the other one then? I guess that is happening due to CPU cache and busy waiting. The thread just finished the work is "hot", it is in CPU cache and ready to lock the mutex. Before go to sleep it also might try to busy wait for mutex few cycles, which increases its chances to win even more.
To fix this, we can either remove the sleep in producer (so it will wake up other threads more often, so other threads will be "hot" as well), or do a sleep() in the consumer instead of yield() (so this thread becomes "cold" during the sleep).
Anyway, there is no opportunity to do the work in parallel due to mutex, so the fact that same thread does most of the work is completely natural IMO.
I have the following code below. I want only half of the threads to enter the threadedfunction at a time. How do I create a Semaphore to block the other processes? And how would I go about unblocking the previously blocked processes whenever the threads have finished using the function?
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
using namespace std;
#define NUM_THREADS 4
long int sharedcount;
pthread_mutex_t count_mutex;
//Function that will be run by multiple threads
//Needs to return a void pointer and if it takes arguments
//it needs to be a void pointer
void *ThreadedFunction(void *threadid)
{
int success;
long id = (long)threadid;
//Lock mutex preventing the other threads from ru nning
success = pthread_mutex_lock( &count_mutex );
cout << "Thread " << id << " beginning.\n";
for(int i = 0; i < 100000000; i++)
sharedcount++;
cout << "Thread " << id << " exiting.\n";
cout << sharedcount << endl;
//Unlock the mutex after the thread has finished running
pthread_mutex_unlock( &count_mutex );
//Kill the thread
pthread_exit(NULL);
}
int main ()
{
//Initialize mutex
pthread_mutex_init(&count_mutex, NULL);
//Create an array of threads
pthread_t threads[NUM_THREADS];
int rc;
int i;
sharedcount = 0;
for( i=0; i < NUM_THREADS; i++ )
{
cout << "main() : creating thread, " << i << endl;
//Create thread by storing it in a location in the array. Call the
//function for the threads to run inside. And pass the argument (if any).
//If no arguments pass NULL
rc = pthread_create(&threads[i], NULL, ThreadedFunction, (void *)i);
if (rc)
{
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
//Have main thread wait for all other threads to stop running.
for(i = 0; i < NUM_THREADS; i++)
pthread_join(threads[i], NULL);
//cout << sharedcount << endl;
pthread_exit(NULL);
}
What you could do is use a counting semaphore (as opposed to a binary semaphore). A counting semaphore has an initial value greater than 1, allowing for multiple threads to call "wait" on the semaphore and not have those threads actually blocked and put in the semaphore queue.
What I would have done in your case is initialize a semaphore in the main function with an initial value of NUM_THREADS/2. Then I would insert a line at the beginning of threadedFunction where I do a wait(semaphore) and a line at the end of the function where you do a signal(semaphore). This way, when a thread is about to exit the function, it signals a thread that was blocked after having called wait on the semaphore and it lets this thread in.
Hope this helps.
everyone.
I am new to semaphore and recently I am learning to implement a simple problem using binary semaphores and i have some questions.
So there is a visiting room, at one time only one person can go in. In my design there are three queues of people (which are all the threads i created). For example, after the person in the second queue visited that room, the next person who is going to enter the room is the top one waiting in third queue, rather the first queue's person. The number of total people is given. and after leaving, just simply terminate the thread.
I am trying to create three semaphores to handle this, i.e, after one person in second queue enters, then block the second queue and ONLY "signal" the third queue to continue. and so on so forth. However, the code has some problems. here I just show some semaphore part of code.
int the main:
sem_init(&mutex, 0, 1);
sem_init(&s0, 0, 1);
sem_init(&s1, 0, 1);
sem_init(&s2, 0, 1);
// create 100 pthread and randomly put into queue0 or queue1 or queue2
for(int i = 0; i<num_thread; i++){
pthread_t curr_thread;
if(queueId == 0){
queue0.push(curr_thread);
}else if(queueId == 1){
queue1.push(curr_thread);
}else if(queueId == 2){
queue2.push(curr_thread);
}
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&curr_thread, &attr, &thread_function, &queue_Num);
pthread_attr_destroy (&attr);
}
in the thread function:
void* thread_function (void* arg){
sem_wait(&mutex);
int n = *((int*) arg);
if(n==0){
sem_wait(&s0);
cout << "person in queue" << n << " is visiting" << endl;
sleep(1);
if(!queue0.empty()){
queue0.pop();
}else{
n++;
}
sem_post(&s1);
}else if(n==1){
sem_wait(&s1);
cout << "person in queue" << n << " is visiting" << endl;
sleep(1);
if(!queue1.empty()){
queue1.pop();
}else{
n++;
}
sem_post(&s2);
}else if(n==2){
sem_wait(&s2);
cout << "person in queue" << n << " is visiting" << endl;
sleep(1);
if(!queue2.empty()){
queue2.pop();
}else{
n++;
}
sem_post(&s0);
}
sem_post(&mutex);
return NULL;
}
Actually when I run it, seems like I met "deadlock", the main finished with showing only 2 threads every time. I thought there must be some problems in the designing of the thread_function. Is there anybody can help point it out and tell me how to fix it? Thanks advance.
When you pass your queueId to the threads, you don't want to pass it a pointer to one of your local variables, because you are going to be changing that very quickly. You should instead just be passing in the integer itself to your threads:
pthread_create(&curr_thread, &attr, &thread_function, (void*)queueId);
// Pass queueId the int, not a pointer
Then, when you need to read the value in your threads, just cast the void* back to an integer:
void* thread_function (void* arg){
...
int n = (long)arg;
..
}
After this, your code works great, for me.
I am trying an example, which causes race condition to apply the mutex. However, even with the mutex, it still happens. What's wrong? Here is my code:
#include <iostream>
#include <boost/thread.hpp>
#include <vector>
using namespace std;
class Soldier
{
private:
boost::thread m_Thread;
public:
static int count , moneySpent;
static boost::mutex soldierMutex;
Soldier(){}
void start(int cost)
{
m_Thread = boost::thread(&Soldier::process, this,cost);
}
void process(int cost)
{
{
boost::mutex::scoped_lock lock(soldierMutex);
//soldierMutex.lock();
int tmp = count;
++tmp;
count = tmp;
tmp = moneySpent;
tmp += cost;
moneySpent = tmp;
// soldierMutex.unlock();
}
}
void join()
{
m_Thread.join();
}
};
int Soldier::count, Soldier::moneySpent;
boost::mutex Soldier::soldierMutex;
int main()
{
Soldier s1,s2,s3;
s1.start(20);
s2.start(30);
s3.start(40);
s1.join();
s2.join();
s3.join();
for (int i = 0; i < 100; ++i)
{
Soldier s;
s.start(30);
}
cout << "Total soldier: " << Soldier::count << '\n';
cout << "Money spent: " << Soldier::moneySpent << '\n';
}
It looks like you're not waiting for the threads started in the loop to finish. Change the loop to:
for (int i = 0; i < 100; ++i)
{
Soldier s;
s.start(30);
s.join();
}
edit to explain further
The problem you saw was that the values printed out were wrong, so you assumed there was a race condition in the threads. The race in fact was when you printed the values - they were printed while not all the threads had a chance to execute
Based on this and your previous post (were it does not seem you have read all the answers yet). What you are looking for is some form of synchronization point to prevent the main() thread from exiting the application (because when the main thread exits the application all the children thread die).
This is why you call join() all the time to prevent the main() thread from exiting until the thread has exited. As a result of your usage though your loop of threads is not parallel and each thread is run in sequence to completion (so no real point in using the thread).
Note: join() like in Java waits for the thread to complete. It does not start the thread.
A quick look at the boost documentation suggests what you are looking for is a thread group which will allow you to wait for all threads in the group to complete before exiting.
//No compiler so this is untested.
// But it should look something like this.
// Note 2: I have not used boost::threads much.
int main()
{
boost::thread_group group;
boost::ptr_vector<boost::thread> threads;
for(int loop = 0; loop < 100; ++loop)
{
// Create an object.
// With the function to make it start. Store the thread in a vector
threads.push_back(new boost::thread(<Function To Call>));
// Add the thread to the group.
group.add(threads.back());
}
// Make sure main does not exit before all the threads have completed.
group.join_all();
}
If we go back to your example and retrofit your Soldier class:
int main()
{
boost::thread batallion;
// Make all the soldiers part of a group.
// When you start the thread make the thread join the group.
Soldier s1(batallion);
Soldier s2(batallion);
Soldier s3(batallion);
s1.start(20);
s2.start(30);
s3.start(40);
// Create 100 soldiers outside the loo
std::vector<Soldier> lotsOfSoldiers;
lotsOfSoldiers.reserve(100); // to prevent reallocation in the loop.
// Because you are using objects we need to
// prevent copying of them after the thread starts.
for (int i = 0; i < 100; ++i)
{
lotsOfSoldiers.push_back(Solder(batallion));
lotsOfSoldiers.back().start(30);
}
// Print out values while threads are still running
// Note you may get here before any thread.
cout << "Total soldier: " << Soldier::count << '\n';
cout << "Money spent: " << Soldier::moneySpent << '\n';
batallion.join_all();
// Print out values when all threads are finished.
cout << "Total soldier: " << Soldier::count << '\n';
cout << "Money spent: " << Soldier::moneySpent << '\n';
}