C++0x has no semaphores? How to synchronize threads?
You can easily build one from a mutex and a condition variable:
#include <mutex>
#include <condition_variable>
class semaphore {
std::mutex mutex_;
std::condition_variable condition_;
unsigned long count_ = 0; // Initialized as locked.
public:
void release() {
std::lock_guard<decltype(mutex_)> lock(mutex_);
++count_;
condition_.notify_one();
}
void acquire() {
std::unique_lock<decltype(mutex_)> lock(mutex_);
while(!count_) // Handle spurious wake-ups.
condition_.wait(lock);
--count_;
}
bool try_acquire() {
std::lock_guard<decltype(mutex_)> lock(mutex_);
if(count_) {
--count_;
return true;
}
return false;
}
};
Segmentation fault usint semaphores to synchronize 3 threads in C
Running your code in a debugger reveals the location of the seg-fault. With backtrace line 41 or main.c (sem_init(sem1, 0, 1);
).
Reading symbols from a.out...done.
(gdb) run
Starting program: /home/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main () at main.c:41
41 sem_init(sem1, 0, 1);
(gdb) next
Program received signal SIGSEGV, Segmentation fault.
__new_sem_init (sem=0x0, pshared=0, value=1) at sem_init.c:44
44 sem_init.c: No such file or directory.
(gdb) bt
#0 __new_sem_init (sem=0x0, pshared=0, value=1) at sem_init.c:44
#1 0x00000000004008a6 in main () at main.c:41
The issue is that sem1
is an initialised pointer. You need to pass a pointer to an instantiated sem_t
object.
sem_t sem1;
sem_t sem2;
sem_t sem3;
Then:
sem_init( &sem1, 0, 1);
sem_init( &sem2, 0, 0);
sem_init( &sem3, 0, 0);
and change sem1
to &sem1
etc. elsewhere of course.
Note that while that stops your code from seg-faulting, it hangs because neither thread waits on sem1
. Probably printA()
should wait on sem1
rather then sem2
.
Sync threads with Posix Semaphores
You seem to have a workable approach: each thread waits on one semaphore, and later posts another to let the next thread run. For that to work, however, each thread should wait for its semaphore before performing its work (i.e. print its message).
Additionally, it looks like your thread functions are using the wrong semaphores. For printone()
to run first, it must wait on the semaphore that you initialize with value 1. For printtwo()
to run next, it must wait on whichever semaphore printone()
posts to. Similarly, for printthree()
.
As a secondary matter, if your thread functions are not going to use their argument, then it would be best to pass NULL
as the third argument to pthread_create()
.
Can POSIX named semaphores synchronize threads?
Yes, they synchronize threads.
The Open Group Base Specification Issue 7 clarifies under General Concepts that all semaphores synchronize threads, whether they are POSIX-style (<semaphore.h>
) or SysV-style (<sys/sem.h>
):
[T]the semaphore lock operation shall cause the calling thread to be blocked and added to the set of threads awaiting the semaphore
Regarding your remark that "unnamed semaphores are either thread- or process-related, but not both", I don't quite know what you mean. Unnamed semaphores may be shared between (parent-child) processes if allocated in shared memory and explicitly initialized as "pshared". However, process-shared or not, unnamed semaphores synchronize individual threads.
(For what it's worth, POSIX mutexes may also be shared between processes.)
Can C++11 condition_variables be used to synchronize processes?
No, those are meant to synchronize threads within one process, not processes.
Interprocess communication is implemented by using shared files. An interprocess mutex or shared memory is just a file (created in your temp folder for instance) to exchange information (data, locks) between two processes. boost::interprocess
offers an nice implementation of that (it does not require any link, code is compiled on the fly, you just need to include it).
To synchronize processes, you should have a look at boost::interprocess. It offers synchronization mechanisms. It offers an interprocess semaphore.
Related Topics
Why How to Not Push_Back a Unique_Ptr into a Vector
When Is the "Typename" Keyword Necessary
Why Copying Stringstream Is Not Allowed
How to Detect Whether There Is a Specific Member Variable in Class
Why Does C++ Disallow Anonymous Structs
How to Correctly Implement Custom Iterators and Const_Iterators
How to Debug Heap Corruption Errors
C++11 Make_Pair With Specified Template Parameters Doesn't Compile
How to Call a Parent Class Function from Derived Class Function
Why How to Use Auto on a Private Type
Is Std::Vector So Much Slower Than Plain Arrays
Calling Delete on Variable Allocated on the Stack
Splitting Templated C++ Classes into .Hpp/.Cpp Files - Is It Possible
Why Should One Not Derive from C++ Std String Class
Post-Increment and Pre-Increment Within a 'For' Loop Produce Same Output