people. I was trying to use mutex as a subtitute for atomic variables, but has the resut demonstrates,it seems that the mutex is not instante, because the "num" still have time to half change, making the if condition true.
Is this supose to work like that, or im i just doing :().
Comente please.. THankes:D
#include <iostream>
#include <pthread.h>
#include <mutex>
using namespace std;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int num = 450;
void* print1 (void* e){
while(1){
if(num != 450 && num != 201 ){
cout << "num-> "<<num<<endl;
}
pthread_mutex_lock(&mutex);
Sleep(0.5);
num = 450;
pthread_mutex_unlock(&mutex);
}
}
void* print2 (void* e){
while(1){
if(num != 450 && num != 201 ){
cout << "num-> "<<num<<endl;
}
pthread_mutex_lock(&mutex);
Sleep(0.5);
num = 201;
pthread_mutex_unlock(&mutex);
}
}
int main(){
pthread_t* threads1;
threads1 = new pthread_t;
pthread_t* threads2;
threads2 = new pthread_t;
//-------------------------------------
pthread_create(threads1,NULL,print1,(void*)NULL);
pthread_create(threads2,NULL,print2,(void*)NULL);
pthread_join(*threads1,(void**)NULL);
pthread_join(*threads2,(void**)NULL);
return false;
}
Result:
num-> 450
num-> 450
num-> 450
num-> 450
...
I was expecting:
(blanck)...
Your code does not synchronize read access to the shared num variable with write access to the same variable. This is clearly visible when compiling with -fsanitize=thread:
WARNING: ThreadSanitizer: data race (pid=3082)
Write of size 4 at 0x0000006020d0 by thread T1 (mutexes: write M9):
#0 print1(void*) test.cc:19 (test+0x000000400df0)
#1 <null> <null> (libtsan.so.0+0x000000024459)
Previous read of size 4 at 0x0000006020d0 by thread T2:
#0 print2(void*) test.cc:27 (test+0x000000400e3f)
#1 <null> <null> (libtsan.so.0+0x000000024459)
Read access needs some form of synchronization as well, not just write access. Otherwise, you may not even observe updates, or see inconsistent data. The details are a consequence of the C++ memory model.
Related
Since the examples for pthreads with pthread_cond_broadcast wakeup are sparse i wrote one, but are unsure if this is correctly synchronized and the way to do it:
do all threads share the same c and mtx variable?
is it necessary upon pthread_cond_wait return to test if some condition is actually met? in my case every call to broadcast should wake up every thread exactly once, but no-one else should do so. (do i prevent spurious wakeups?)
the program currently does not exit despite async cancel type. also no success with deferred cancellation tried in example code despite pthread_cond_wait being a cancellation point so.
overall does it work like i expect it to.
#include <pthread.h>
#include <iostream>
#include <unistd.h>
struct p_args{
int who;
};
pthread_cond_t c; //share between compilation units
pthread_mutex_t mtx;
void *threadFunc(void *vargs){
//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
struct p_args * args = (struct p_args *) vargs;
while(true){
//wait for trigger one loop
pthread_mutex_lock(&mtx);
pthread_cond_wait(&c, &mtx);
pthread_mutex_unlock(&mtx);
//should be entangled output showing concurrent execution
std::cout << "t " << args->who << std::endl;
/* expensive work */
}
delete args;
}
int main(int argc, char* argv[])
{
pthread_cond_init(&c, NULL);
pthread_mutex_init(&mtx, NULL);
pthread_t thread_id[2];
struct p_args *args0 = new p_args();
struct p_args *args1 = new p_args();
args0->who = 0;
args1->who = 1;
pthread_create(&thread_id[0], NULL, threadFunc, args0);
pthread_create(&thread_id[1], NULL, threadFunc, args1);
sleep(3);
pthread_mutex_lock(&mtx);
pthread_cond_broadcast(&c);
pthread_mutex_unlock(&mtx);
sleep(3);//test if thread waits
pthread_cancel(thread_id[0]);
pthread_cancel(thread_id[1]);
pthread_join (thread_id[0], NULL);
pthread_join (thread_id[1], NULL);
//could perform cleanup here
return 0;
}
Regarding exiting deferred:
thread_id[0] exits fine and i am stuck in line `pthread_join (thread_id[1], NULL);`, it says (Exiting) but seems stuck on a lock, with debugger:
<br>
[![enter image description here][2]][2]
<br>
EDIT final solution i came up with:
#include <pthread.h>
#include <iostream>
#include <unistd.h>
struct p_args{
int who;
};
pthread_cond_t c;
pthread_mutex_t mtx;
bool doSome[2];
bool exitFlag;
void *threadFunc(void *vargs){
struct p_args * args = (struct p_args *) vargs;
while(true){
//wait for trigger one loop
pthread_mutex_lock(&mtx);
do {
pthread_cond_wait(&c, &mtx);
if(exitFlag) {
std::cout << "return " << args->who << std::endl;
delete args;
pthread_mutex_unlock(&mtx);
return NULL;
}
} while(doSome == false);
doSome[args->who] = false;
pthread_mutex_unlock(&mtx);
std::cout << "t " << args->who << std::endl;
}
}
int main(int argc, char* argv[])
{
pthread_cond_init(&c, NULL);
pthread_mutex_init(&mtx, NULL);
pthread_t thread_id[2];
struct p_args *args0 = new p_args();
struct p_args *args1 = new p_args();
args0->who = 0;
args1->who = 1;
doSome[0] = doSome[1] = true;
exitFlag = false;
pthread_create(&thread_id[0], NULL, threadFunc, args0);
pthread_create(&thread_id[1], NULL, threadFunc, args1);
doSome[0] = doSome[1] = true;
pthread_cond_broadcast(&c);
sleep(3);
doSome[0] = doSome[1] = true;
pthread_cond_broadcast(&c);
sleep(3);
exitFlag = true;
pthread_cond_broadcast(&c);
pthread_join (thread_id[0], NULL);
pthread_join (thread_id[1], NULL);
return 0;
}
do all threads share the same c and mtx variable?
Yes, just like any other global variable. You could print their addresses from each thread to confirm it.
is it necessary upon pthread_cond_wait return to test if some condition is actually met?
Yes, all wait interfaces are subject to spurious wakeups, and you're always responsible for checking your own predicate. See the documentation or a good book.
the program currently does not exit ...
pthread_cancel is uniformly horrible and should never be used. It's really hard to get right. If you want to tell your thread to exit, write a notification mechanism - build it into the existing predicate loop - and signal/broadcast to make sure all threads wake up and realize it's time to die.
Regarding exiting deferred: thread_id[0] exits fine and i am stuck in line pthread_join (thread_id[1], NULL);, it says (Exiting) but seems stuck on a lock
One of the hard things about pthread_cancel is cleanup. If cancellation occurs while you're holding a lock, you need to have used pthread_cleanup_push to emulate cancel-compatible RAII semantics. Otherwise the first thread may (and in this case, did) die with the mutex still locked.
In this case the second thread is trying to exit from pthread_const_wait due to cancellation, but it needs to regain the lock and can't.
The usual form of a condition variable loop is this (and a good reference book should show something similar):
void *thread(void *data)
{
struct Args *args = (struct Args *)data;
/* this lock protects both the exit and work predicates.
* It should probably be part of your argument struct,
* globals are not recommended.
* Error handling omitted for brevity,
* but you should really check the return values.
*/
pthread_mutex_lock(&args->mutex);
while (!exit_predicate(args)) {
while (!work_predicate(args)) {
/* check the return value here too */
pthread_cond_wait(&args->condition, &args->mutex);
}
/* work_predicate() is true and we have the lock */
do_work(args);
}
/* unlock (explicitly) only once.
* If you need to cope with cancellation, you do need
* pthread_cleanup_push/pop instead.
*/
pthread_mutex_unlock(&args->mutex);
return data;
}
where your custom code can just go in bool exit_predicate(struct Args*), bool work_predicate(struct Args*) and void do_work(struct Args*). The loop structure itself rarely needs much alteration.
A thread which hold mutex died. Another thread will deadlock when it calls "pthread_mutex_lock", although I use "PTHREAD_MUTEX_ERRORCHECK" attribute.
#include <pthread.h>
#include <iostream>
#include <unistd.h>
using namespace std;
pthread_mutex_t mutex;
void *handler(void *)
{
cout << "child thread" << endl;
int ret = pthread_mutex_lock(&mutex);
cout << "child ret: " << ret << endl;
pthread_exit(NULL);
}
int main()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex, &attr);
pthread_mutexattr_destroy(&attr);
pthread_t tid;
pthread_create(&tid, NULL, handler, NULL);
sleep(2);
cout << "father awake" << endl;
int ret = pthread_mutex_lock(&mutex);
cout << "father ret: " << ret << endl;
return 0;
}
Output:
[LINUX ENVIRONMENT]: Linux ubuntu 3.19.0-25-generic #26~14.04.1-Ubuntu SMP
You are perhaps thinking of the robust attribute of mutexes (pthread_mutexattr_setrobust()), rather than of the errorcheck type of mutex. A robust mutex would have notified your main thread that the holder of the mutex's lock had terminated with EOWNERDEAD.
The PTHREAD_MUTEX_ERRORCHECK type, on the other hand, simply guards against three kinds of errors:
attempting to recursively lock one's own locked mutex (not applicable here)
attempting to unlock a mutex locked by another thread (not applicable here)
attempting to unlock an unlocked mutex (not applicable here)
This is a small example of using the pthread_mutexattr_setrobust call to allow for setting the mutex that was never unlocked back to a consistent state:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t lock;
void dropped_thread(void)
{
printf("Setting lock...\n");
pthread_mutex_lock(&lock);
printf("Lock set, now exiting without unlocking...\n");
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t lock_getter;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
pthread_mutex_init(&lock, &attr);
pthread_mutexattr_destroy(&attr);
pthread_create(&lock_getter, NULL, (void *) dropped_thread, NULL);
sleep(2);
printf("Inside main\n");
printf("Attempting to acquire unlocked mutex?\n");
pthread_mutex_consistent(&lock);
pthread_mutex_unlock(&lock);
pthread_mutex_lock(&lock);
printf("Successfully acquired lock!\n");
pthread_mutex_destroy(&lock);
return 0;
}
As you can see by making the call to pthread_mutex_consistent after setting the mutex robustness, its state is marked as consistent again.
I have a simple threaded program which use a conditional variable and a rwlock. I've been staring at it for hours trying different approaches. The problem is that a thread or more stops at the rwlock after a while although it is not locked for writing. Maybe I miss something about how those locks work or how they are implemented.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <unistd.h>
//global variables
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_rwlock_t rwlock;
int counter;
int listLength = 1;
void* worker(void* arg){
do {
usleep(200);
printf("Before rwlock\n");
pthread_rwlock_rdlock(&rwlock);
printf("Before mutex\n");
pthread_mutex_lock(&mutex);
printf("Afer mutex\n");
counter++;
//signal the main
if (counter == 5 ||
(listLength < 5 && counter == listLength)){
printf("Signal main\n");
pthread_cond_signal(&cond);
counter = 0;
}
pthread_mutex_unlock(&mutex);
pthread_rwlock_unlock(&rwlock);
} while(listLength != 0);
return NULL;
}
int main(int argc, char* argv[]){
if (argc != 2){
perror("Invalid number of args");
exit(1);
}
//get arguments
int workers = atoi(argv[1]);
//initialize sync vars
pthread_rwlockattr_t attr;
pthread_rwlockattr_setkind_np(&attr,
PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_rwlock_init(&rwlock, &attr);
counter = 0;
//create threads
pthread_t threadArray[workers];
int threadOrder[workers];
for (int i = 0; i < workers; i++){
threadOrder[i] = i;
if (pthread_create(&threadArray[i], NULL,
worker, &threadOrder[i]) != 0){
perror("Cannot create thread");
exit(1);
}
}
while(listLength != 0) {
//wait for signal and lock the list
pthread_mutex_lock(&mutex);
while (pthread_cond_wait(&cond, &mutex) != 0);
pthread_rwlock_wrlock(&rwlock);
printf("In write lock\n");
pthread_mutex_unlock(&mutex);
pthread_rwlock_unlock(&rwlock);
printf("release wrlock\n");
}
//join the threads
for (int i = 0; i < workers; i++){
if (pthread_join(threadArray[i], NULL) !=0){
perror("Cannot join thread");
exit(1);
}
}
//release resources
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
pthread_rwlock_destroy(&rwlock);
return 0;
}
Looks like this code has several inconsistencies in it.
You're using mutex together with rwlock which means that all the threads of this kind are always locked. If you remove the rwlock code - it won't change the behaviour.
I cannot see the pthread_rwlock_init() call, and suppose you've called it in another place. Anyway pay attention you do call it and you don't call it twice or more times with the same rowlock object.
The same applies to pthread_rwlockattr_destroy()
I cannot see the reason why pthread_rwlock_rdlock() would block without write lock. Be sure you don't do it. Or else you could do a mutual lock of your mutex
Can anyone shed light on the reason that when the below code is compiled and run on OSX the 'bartender' thread skips through the sem_wait() in what seems like a random manner and yet when compiled and run on a Linux machine the sem_wait() holds the thread until the relative call to sem_post() is made, as would be expected?
I am currently learning not only POSIX threads but concurrency as a whole so absoutely any comments, tips and insights are warmly welcomed...
Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
//using namespace std;
#define NSTUDENTS 30
#define MAX_SERVINGS 100
void* student(void* ptr);
void get_serving(int id);
void drink_and_think();
void* bartender(void* ptr);
void refill_barrel();
// This shared variable gives the number of servings currently in the barrel
int servings = 10;
// Define here your semaphores and any other shared data
sem_t *mutex_stu;
sem_t *mutex_bar;
int main() {
static const char *semname1 = "Semaphore1";
static const char *semname2 = "Semaphore2";
pthread_t tid;
mutex_stu = sem_open(semname1, O_CREAT, 0777, 0);
if (mutex_stu == SEM_FAILED)
{
fprintf(stderr, "%s\n", "ERROR creating semaphore semname1");
exit(EXIT_FAILURE);
}
mutex_bar = sem_open(semname2, O_CREAT, 0777, 1);
if (mutex_bar == SEM_FAILED)
{
fprintf(stderr, "%s\n", "ERROR creating semaphore semname2");
exit(EXIT_FAILURE);
}
pthread_create(&tid, NULL, bartender, &tid);
for(int i=0; i < NSTUDENTS; ++i) {
pthread_create(&tid, NULL, student, &tid);
}
pthread_join(tid, NULL);
sem_unlink(semname1);
sem_unlink(semname2);
printf("Exiting the program...\n");
}
//Called by a student process. Do not modify this.
void drink_and_think() {
// Sleep time in milliseconds
int st = rand() % 10;
sleep(st);
}
// Called by a student process. Do not modify this.
void get_serving(int id) {
if (servings > 0) {
servings -= 1;
} else {
servings = 0;
}
printf("ID %d got a serving. %d left\n", id, servings);
}
// Called by the bartender process.
void refill_barrel()
{
servings = 1 + rand() % 10;
printf("Barrel refilled up to -> %d\n", servings);
}
//-- Implement a synchronized version of the student
void* student(void* ptr) {
int id = *(int*)ptr;
printf("Started student %d\n", id);
while(1) {
sem_wait(mutex_stu);
if(servings > 0) {
get_serving(id);
} else {
sem_post(mutex_bar);
continue;
}
sem_post(mutex_stu);
drink_and_think();
}
return NULL;
}
//-- Implement a synchronized version of the bartender
void* bartender(void* ptr) {
int id = *(int*)ptr;
printf("Started bartender %d\n", id);
//sleep(5);
while(1) {
sem_wait(mutex_bar);
if(servings <= 0) {
refill_barrel();
} else {
printf("Bar skipped sem_wait()!\n");
}
sem_post(mutex_stu);
}
return NULL;
}
The first time you run the program, you're creating named semaphores with initial values, but since your threads never exit (they're infinite loops), you never get to the sem_unlink calls to delete those semaphores. If you kill the program (with ctrl-C or any other way), the semaphores will still exist in whatever state they are in. So if you run the program again, the sem_open calls will succeed (because you don't use O_EXCL), but they won't reset the semaphore value or state, so they might be in some odd state.
So you should make sure to call sem_unlink when the program STARTS, before calling sem_open. Better yet, don't use named semaphores at all -- use sem_init to initialize a couple of unnamed semaphores instead.
AIX (and HPUX if anyone cares) have a nice little feature called msemaphores that make it easy to synchronize granular pieces (e.g. records) of memory-mapped files shared by multiple processes. Is anyone aware of something comparable in linux?
To be clear, the msemaphore functions are described by following the related links here.
POSIX semaphores can be placed in memory shared between processes, if the second argument to sem_init(3), "pshared", is true. This seems to be the same as what msem does.
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
int main() {
void *shared;
sem_t *sem;
int counter, *data;
pid_t pid;
srand(time(NULL));
shared = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_SHARED, -1, 0);
sem_init(sem = shared, 1, 1);
data = shared + sizeof(sem_t);
counter = *data = 0;
pid = fork();
while (1) {
sem_wait(sem);
if (pid)
printf("ping>%d %d\n", data[0] = rand(), data[1] = rand());
else if (counter != data[0]) {
printf("pong<%d", counter = data[0]);
sleep(2);
printf(" %d\n", data[1]);
}
sem_post(sem);
if (pid) sleep(1);
}
}
This is a pretty dumb test, but it works:
$ cc -o test -lrt test.c
$ ./test
ping>2098529942 315244699
pong<2098529942 315244699
pong<1195826161 424832009
ping>1195826161 424832009
pong<1858302907 1740879454
ping>1858302907 1740879454
ping>568318608 566229809
pong<568318608 566229809
ping>1469118213 999421338
pong<1469118213 999421338
ping>1247594672 1837310825
pong<1247594672 1837310825
ping>478016018 1861977274
pong<478016018 1861977274
ping>1022490459 935101133
pong<1022490459 935101133
...
Because the semaphore is shared between the two processes, the pongs don't get interleaved data from the pings despite the sleeps.
This can be done using POSIX shared-memory mutexes:
pthread_mutexattr_t attr;
int pshared = PTHREAD_PROCESS_SHARED;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, &pshared);
pthread_mutex_init(&some_shared_mmap_structure.mutex, &attr);
pthread_mutexattr_destroy(&attr);
Now you can unlock and lock &some_shared_mmap_structure.mutex using ordinary pthread_mutex_lock() etc calls, from multiple processes that have it mapped.
Indeed, you can even implement the msem API in terms of this: (untested)
struct msemaphore {
pthread_mutex_t mut;
};
#define MSEM_LOCKED 1
#define MSEM_UNLOCKED 0
#define MSEM_IF_NOWAIT 1
msemaphore *msem_init(msemaphore *msem_p, int initialvalue) {
pthread_mutex_attr_t attr;
int pshared = PTHREAD_PROCESS_SHARED;
assert((unsigned long)msem_p & 7 == 0); // check alignment
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, &pshared); // might fail, you should probably check
pthread_mutex_init(&msem_p->mut, &attr); // never fails
pthread_mutexattr_destroy(&attr);
if (initialvalue)
pthread_mutex_lock(&attr);
return msem_p;
}
int msem_remove(msemaphore *msem) {
return pthread_mutex_destroy(&msem->mut) ? -1 : 0;
}
int msem_lock(msemaphore *msem, int cond) {
int ret;
if (cond == MSEM_IF_NOWAIT)
ret = pthread_mutex_trylock(&msem->mut);
else
ret = pthread_mutex_lock(&msem->mut);
return ret ? -1 : 0;
}
int msem_unlock(msemaphore *msem, int cond) {
// pthreads does not allow us to directly ascertain whether there are
// waiters. However, a unlock/trylock with no contention is -very- fast
// using linux's pthreads implementation, so just do that instead if
// you care.
//
// nb, only fails if the mutex is not initialized
return pthread_mutex_unlock(&msem->mut) ? -1 : 0;
}
Under Linux, you may be able to achieve what you want with SysV shared memory; quick googling turned up this (rather old) guide that may be of help.