4

I use private field (PushSocket - zmq_push socket for netmq)

private PushSocket _pushSocket;

And two methods which use this socket in different threads

public void Method1()
{
    //.....//
    _pushSocket.SendFrame(....);
    //.....//
}

public void Method2()
{
    //.....//
    _pushSocket.SendFrame(....);
    //.....//
}

Should I use lock or another synchronization primitives?

user3666197
  • 1
  • 6
  • 50
  • 92
Evgeniy Mironov
  • 777
  • 6
  • 22
  • u could try adding inProc sockets and have the worker threads use them to send their messages to the pushSocket. that way you can avoid any thread sync issues. – barakcaf Feb 07 '16 at 16:47

2 Answers2

6

No,

on a basis of understanding the ZeroMQ professional-level recommendation No.1:
one shall not design code with sharing sockets among threads.

By design,
ZeroMQ Scalable Formal Communication Patterns ( a.k.a. a bit misleadingly nicknamed as socket(s) )
are not thread-safe ( and never tried to be ).

It is not a thing of belief in one's capabilities to somehow mediate inter-thread signalling, it is a principal belief, that good scalable parallel code shall never share, nor block.

Thus said ZeroMQ evangelism.

Confused? np.
Angry? np.
Zero-sharing, Zero-locking -- try to consider it as some form of collision avoidance, rather than having to sieve ashes from burnt thrashes of an uncontrolled concurrent havoc.


If in doubt

one has the best option, to read Pieter HINTJENS' book "Code Connected. Volume 1" and spend some time with Pieters views on scalable code design principles.

You will soon fall in love with the new style of thinking ZeroMQ-way.

univ
  • 717
  • 4
  • 12
user3666197
  • 1
  • 6
  • 50
  • 92
  • It's worth noting that [Pieter Hintjens has stated that he believes this could have been the *wrong* choice for ZMQ](http://hintjens.com/blog:84) - the non-thread-safe nature of sockets arises from message frames, which itself arose from the way messages are addressed. We may, at some point, have thread safe sockets if the changes in that linked blog really take hold. But that's an uphill battle (I haven't specifically looked into the current state of the situation, that blog was a year ago and clearly the messaging hasn't changed yet). – Jason Feb 08 '16 at 14:39
  • 1
    **Oh yes**, Jason, **sure** - the ZeroMQ design, based on this initial axiomatic corner-stone **principle, might** sooner or later **evolve** beyond this one, however the non-thread-safeness, as-is, does not reduce the powers of the ZeroMQ concept of thinking. As you have already confirmed, **the question is**, whether that would **bring any *significant* benefit** from vasting so immense efforts spent on total redesign / QA ( just in a name of being later allowed to **sometimes** violate the Zero-sharing principle on allowing a FCP-socket-endpoint to become shared among more than one thread ) – user3666197 Feb 08 '16 at 16:56
  • I don't disagree that ZMQ is just as capable, if a little more complicated than necessary, due to the current design decisions that cause the non-thread-safeness. I also agree with Pieter that the proposed changes *likely would* be beneficial enough to pursue, but may face enough of a hurdle to prevent it from happening any time soon. – Jason Feb 08 '16 at 18:27
2

ZeroMQ sockets are not thread safe. I've solved the similar problem by using BlockingCollection in the following way:

class MyClass 
{
    private PushSocket _pushSocket;

    private BlockingCollection<NetMQMessage> _toSend = new BlockingCollection<NetMQMessage>();

    MyClass() 
    {
        _pushSocket = new PushSocket();
        _pushSocket.Bind("someaddress");

        Task.Factory.StartNew(WorkerThread, TaskCreationOptions.LongRunning);
    }

    private void WorkerThread() 
    {
        while (true) 
        {
            NetMQMessage message = _toSend.Take();

            _pushSocket.SendMultipartMessage(message);
        }
    }

    public void Method1(NetMQMessage message) 
    {
        _toSend.Add(message);
    }

    public void Method2(NetMQMessage message) 
    {
        _toSend.Add(message);
    }
}

You should also implement the appropriate disposal (breaking WorkerThread and disposing _toSend), but this is it.

Aleksandar Pesic
  • 668
  • 7
  • 18