English 中文(简体)
Semaphore 执行
原标题:Semaphore implementation

I was wondering if there was a way to implement semaphore in C++ (or C#), any libraries that d help. I tried using OpenMP but I had no way of actually blocking threads, instead I had to busy wait on em which lead to deadlocks if/when I hadn t enough number of threads. So First I m looking for a some library that would let me block/spawn/kill my threads.
Secondly, are there any libraries out there that already implement semaphores?
And finally, when I was introduced to the context of semaphores I found it very useful (maybe I m wrong?) but I don t see many libraries (if at all) implementing it. I m familiar with OpenMP, looked around Intel s TBB, C# threads. But in none of these I don t see semaphores explicitly. So are semaphores not as practical as I think? Or is it that they re hard to implement? Or is it me not being aware?
P.S.
Can semaphores be implemented cross-platform? Since they re probably related to OS.

最佳回答

Are there any libraries out there that already implement this?
For C++ there are multiple multithreading libraries, which provide Semaphore implementations:

另外,你也可以使用“博恩”实施Semaphores。 , out。

问题回答

增强第一咨询的使用。 所有辛勤工作都已完成。

如果你想看到如何执行,那么就应该看一看(尽管这是一个粗略的图表,我相信,某些研究渠道可以优化)。 从根本上说,从三条东西中就形成了一种ema光:

  • A count
  • A condition variable (that provides the suspend)
  • A mutex which provides the exclusiveness to modify the count and wait on the condition.

Here is the simple version:

#include <pthread.h>

// Need an exception safe locking class.
struct MutexLocker
{
    MutexLocker(pthread_mutex_t& m) :mutex(m)
    { if (pthread_mutex_lock(&mutex) != 0)      {throw int(1); }}
    ~MutexLocker()
    { if (pthread_mutex_unlock(&mutex) != 0)    {throw int(1); }}
    private:
        pthread_mutex_t&    mutex;
};

class Semaphore
{
    public:
        Semaphore(int initCount = 0)
            : count(initCount)
            , waitCount(0)
        {
            if (pthread_mutex_init(&mutex, NULL) != 0)
            {   throw int(1);
            }

            if (pthread_cond_init(&cond, NULL) != 0)
            {   pthread_mutex_destroy(&mutex);
                throw int(2);
            }
        }

        void wait()
        {
            MutexLocker locker(mutex);

            while(count == 0)
            {
                ++waitCount;
                if (pthread_cond_wait(&cond, &mutex) != 0)
                {   throw int(2);
                }

                // A call to pthread_cond_wait() unlocks the mutex and suspends the thread.
                // It does not busy wait the thread is suspended.
                //
                // When a condition variable receives apthread_cond_signal() a random thread
                // is un-suspended. But it is not released from the call to wait
                // until the mutex can be reacquired by the thread.
                //
                // Thus we get here only after the mutex has been locked.
                //
                // You need to use a while loop above because of this potential situation.
                //      Thread A:  Suspended waiting on condition variable.
                //      Thread B:  Working somewhere else.
                //      Thread C:  calls signal() below (incrementing count to 1)
                //                 This results in A being awakened but it can not exit pthread_cond_wait()
                //                 until it requires the mutex with a lock. While it tries to
                //                 do that thread B finishes what it was doing and calls wait()
                //                 Thread C has incremented the count to 1 so thread B does not
                //                 suspend but decrements the count to zero and exits.
                //                 Thread B now aquires the mutex but the count has been decremented to
                //                 zero so it must immediately re-suspend on the condition variable.


                // Note a thread will not be released from wait until
                // it receives a signal and the mustex lock can be re-established.

                --waitCount;
            }

            --count;
        }

        void signal()
        {

            // You could optimize this part with interlocked increment.
            MutexLocker locker(mutex);
            ++count;

            // This Comment based on using `interlocked increment` rather than mutex.
            //
            // As this part does not modify anything you don;t actually need the lock.
            // Potentially this will release more threads than you need (as you don t
            // have exclusivity on reading waitCount but that will not matter as the
            // wait() method does and any extra woken threads will be put back to sleep.

            // If there are any waiting threads let them out.
            if (waitCount > 0)
            {   if  (pthread_cond_signal(&cond) != 0)
                {   throw int(2);
                }
            }
        }
    private:
        unsigned int        count;
        unsigned int        waitCount;
        pthread_mutex_t     mutex;
        pthread_cond_t      cond;
};

In .NET, there exists an implementation within the BCL: System.Threading.Semaphore.

For native code on Windows, have a look at the CreateSemaphore Function. If you are targeting Linux, then you can find a semaphore implementation of the Vienna University of Technology here (which I have already used before and works).

在C++中,为了阻挡read线,我建议你使用条件变量,而不是烟雾。 在C#中,monitors 可能更合适。

Even for a rather simple case of Producer-Consumer problem, a semaphore-based solution is harder to do right: doing semaphore increments & decrements in a wrong order could result in problems. On the contrary, a condition-variable-based solution would not have such issues: condition variables are used with a lock (mutex) and the right order of operations is imposed automatically; so after wakeup, a thread already has the lock acquired.

See also my asnwer to 我何时应该使用ema磷? 我认为,如果我举另一个情况变数的例子,更适合经常用摩擦解决问题。

And to address another your question, I think higher liability to erroneous use and higher complexity of solutions (comparing to alternatives) are the reason why semaphores are not provided by some threading packages. For TBB, I can say that for sure. Thread support in C++11 (designed after Boost.Thread) does not have it too; see Anthony Williams answer why.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签