Are netty channels (or java NIO channels in general) FIFO? or I need to implement FIFO by myself using sequence numbers?
Thanks
NIO maintains a read and write lock internally; however they are implemented using a synchronized block in NIO.
There is NO guarantee that Thread B will obtain the lock after Thread A when using synchronized. It is entirely possible that Thread C could obtain write lock before Thread B.
See the following on lock release: Synchronized release order
If you NEED guaranteed FIFO across many threads then you need to create a ReentrantLock with fair=true and require all of your threads to obtain that lock first.
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantLock.html
Maintaining order is not the responsibility of the transport layer.so your send message A and message B through the same channel(same socket),on the server side the message arrived order is uncertain.
Meet these conditions the message arrived order is send order:
use TCP protocol
message A and message B send in one system call
if you need order your application should do it.
Related
I have some threads which are writing on the same MulticastSocket (depending by the scheduling, probably can happen than more then one thread is writing on the MulticastSocket at the same time). Do I have to get them write on it one per timer by using some form of locking, or the UDP protocol is doing this implicitly?
It doesn't really have anything to do with UDP. The documentation for MulticastSocket doesn't say it's threadsafe, so you can't assume it's threadsafe. You can't know that it doesn't update internal structures (such as an outbound buffer) which could be damaged by simultaneous access.
If all the threads are using the same instance of MulticastSaocket, you'll want to ensure they don't simultaneously call its methods. You can do that easily enough by synchronizing on the instance:
synchronized (theSocket) {
theSocket.send(/*...*/);
}
I have a socketChannel (java.nio.channels.SocketChannel) listening for reading requests (from multiple clients). It stores each request in a Request Queue.
Also socketChannel.configureBlocking(false)
Then I want the multiple threads to take one request at a time from the Request Queue and write to the socketChannel
I have read the following from a documentation.
Socket channels are safe for use by multiple concurrent threads. They
support concurrent reading and writing, though at most one thread may
be reading and at most one thread may be writing at any given time.
Since only 1 thread can be written, what can I do in the case of multiple writes?
You can use your own lock synchronized or ReentrantLock, or queue the messages and have one thread do the actual writes.
The problem with writes is you can only atomically write one byte at a time, if you write more than one byte, you might send some, but not all of the data in which case another thread can attempt to write it's message and you get a corrupted message.
I have a java.nio.channels.SocketChannel listening for reading requests (from multiple clients).
No you don't. You might have a ServerSocketChannel that listens for connections from multiple clients, but once you have an accepted SocketChannel, it is only connected to one client. All you can get from it is sequential requests from that client.
It stores each request in a Request Queue.
I don't see any need for that.
Also socketChannel.configureBlocking(false)
Then I want the multiple threads to take one request at a time from the Request Queue and write to the socketChannel
Why not just compute the reply as soon as you read it and write it directly back?
I have read the following from a documentation.
Socket channels are safe for use by multiple concurrent threads. They support concurrent reading and writing, though at most one thread may be reading and at most one thread may be writing at any given time.
Since only 1 thread can be written, what can I do in the case of multiple writes?
What multiple writes? You only have one client request per channel. You only need to write one reponse per request. You should not read, let alone process, a new request until you've written the prior response.
Do we need to create individual channels for each thread or use the same channel for all threads? Also the same question about connection. Do we need to use different connections for each thread or a single connection?
What is the difference when we use one channel across all threads and individual channels for each thread?
Connection:
According to the java doc (https://www.rabbitmq.com/releases/rabbitmq-java-client/v3.6.5/rabbitmq-java-client-javadoc-3.6.5/):
Current implementations are thread-safe for code at the client API level, and in fact thread-safe internally except for code within RPC calls.
Channel:
According to the doc (https://www.rabbitmq.com/api-guide.html):
Channel instances must not be shared between threads. Applications should prefer using a Channel per thread instead of sharing the same Channel across multiple threads. While some operations on channels are safe to invoke concurrently, some are not and will result in incorrect frame interleaving on the wire. Sharing channels between threads will also interfere with * Publisher Confirms.
I'm planning to use an instance of DatagramSocket and call its send method from different threads... to send UDP packets to different clients. Is the method thread safe i.e. calling this method from different threads will not create any trouble/inconsistency/race condition?
Thanks!
UDP guarantees that datagrams arrive intact (if at all). In other words there can be no interleaving even if there is multithreading at the sender. That's all you need. You don't actually need thread safety. However the C send() system call is thread safe, like all system calls, because they are atomic.
Yes. This is only a thin layer on the native OS, which is threadsafe.
See here http://www.velocityreviews.com/forums/t150685-is-datagramsocket-thread-safe.html
The answer is yes, the layer on the native operating system is thread safe.
BUT, because network throughput is limited, if you send more packets than the network can handle, some packets will be dropped.
I'm developing a small client-server program in Java.
The client and the server are connected over one tcp-connection. Most parts of the communication are asynchronous (can happen at any time) but some parts I want to be synchronous (like ACKs for a sent command).
I use a Thread that reads commands from the socket's InputStream and raises an onCommand() event. The Command itself is progressed by the Command-Design-Pattern.
What would be a best-practice approach (Java), to enable waiting for an ACK without missing other, commands that could appear at the same time?
con.sendPacket(new Packet("ABC"));
// wait for ABC_ACK
edit1
Think of it like an FTP-Connection but that both data and control-commands are on the same connection. I want to catch the response to a control-command, while data-flow in the background is running.
edit2
Everything is sent in blocks to enable multiple (different) transmissons over the same TCP-Connection (multiplexing)
Block:
1 byte - block's type
2 byte - block's payload length
n byte - block's paylod
In principle, you need a registry of blocked threads (or better, the locks on which they are waiting), keyed with some identifier which will be sent by the remote side.
For asynchronous operation, you simply sent the message and proceed.
For synchronous operation, after sending the message, your sending thread (or the thread which initiated this) create a lock object, adds this with some key to the registry and then waits on the lock until notified.
The reading thread, when it receives some answer, looks in the registry for the lock object, adds the answer to it, and calls notify(). Then it goes reading the next input.
The hard work here is the proper synchronization to avoid dead locks as well as missing a notification (because it comes back before we added ourself to the registry).
I did something like this when I implemented the remote method calling protocol for our Fencing-applet. In principle RMI works the same way, just without the asynchronous messages.
#Paulo's solution is one I have used before. However, there may be a simpler solution.
Say you don't have a background thread reading results in the connection. What you can do instead do is use the current thread to read any results.
// Asynchronous call
conn.sendMessage("Async-request");
// server sends no reply.
// Synchronous call.
conn.sendMessage("Sync-request");
String reply = conn.readMessage();