synchronized lock on socket object - java

I have a below code in which I am using synchronized on a socket:
public boolean send(final long addr, final byte[] enc, final Socket socket) {
ZMsg msg = new ZMsg();
msg.add(enc);
// using the socket as its own lock while accessing it
boolean sent;
synchronized (socket) {
sent = msg.send(socket);
}
msg.destroy();
retryHolder.put(addr, enc);
return sent;
}
I wanted to understand how this synchronized on a socket will work here? I have around 20 threads calling this send method concurrently and each time Socket can be different. We have around 60 sockets to choose from so all those 20 threads can pick any one socket from 60. It is possible, multiple threads can pick same socket to send data on or multiple threads can pick different socket everytime to send data on. Below are the scenarios I can think of:
All 20 threads picking different socket each time to send data on as we have 60 sockets to work on. So how does synchronized on the socket will work in this scenario? Will it be fast or it will block for any threads?
Out of 20 threads, some threads picking same socket to send data on randomly. So all those threads will wait for others before entering the synchronized block meaning each thread waiting for that socket to get freed up? So will it slow down anything?
Any other case I missed?
Basically I am trying to figure out will there be any performance hit of using socket as the lock by using synchronized keyword for all the scenarios I can hit.

This mechanism is in place to prevent different threads from sending data to the same socket at the same time and mucking up your data. Different threads using different sockets won't block, and although the act of synchronizing is not "free", it's negligible compared to sending data over the network.

If each thread has different socket than other thread. Performance will not be hampered. As no thread will be blocked to get lock on a socket.
Suppose If three threads have same socket. Only one will be allowed to send data on socket. Once it is finished lock will be release and next thread will get lock of the socket and start sending data and then 3rd thread and so on. So here there will be some performance impact. And as you mentioned threads are less in number as compared to sockets. I would advise to change implementation to assign the same socket to a thread only when all the sockets are already assigned to avoid any performance problems.
But yes if socket class is your own class and you can change the code. It is better to add synchronization on send method or preferably on all the methods, so that no other thread can use it if it does not have lock. And if you can not change it you can create wrapper class or proxy for Socket class, and make the methods in proxy class as synchronized.

Related

Creating a Thread inside a while loop?

So I have a server that accepts socket connections and starts a thread for each socket for data transfer etc. A short sum up of the server code:
ServerSocket ss = new SocketServer(7777);
while(true) {
Socket socket = ss.accept();
Runnable r = new aHandler(socket);
new Thread(r).start();
}
Now I have two questions knowing that variables get destroyed after every loop, is the Thread still alive after a loop? And if it does is the socket closed after the loop or is it still running inside the Thread?
Yes too both the socket connection will stay open and the thread will continue to run. For this kind of situation it will be the threads job to close its self. Or else the threads will take more and more ram the more connections you make.
Right, if the server accepts the connection, it can delegate the interaction with the client right away into a new Thread, thus, accepting new connections. Connections stablished and delegated to a Thread will end smoothly when they get closed.
You can check exactly that scenario explained in Java Tutorial here:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
and a working example here:
Server supporting multiple clients:
https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/networking/sockets/examples/KKMultiServer.java
Thread handling connections once it is delegated to it:
https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/networking/sockets/examples/KKMultiServerThread.java
Cheers!
Yes, those threads would be alive. The thread that spun would actually enters your run method and it would continue to execute that.

UDP and Threads - Java

I'm using UDP to communicate through threads, but I want to make some kind of variable to know if the thread waiting for a message has waited too long.
Is there any method inherited by UDP class that I could use?
Or is it a better choice to make my own timekeeper parallel to every thread to keep the time?
Question: If a thread has waited too long for a message, what should it do?
Answer: Stop waiting!
What you should probably do is to call setSoTimeout(int) on the DatagramSocket to set a timeout before you call receive(DatagramPacket). This will cause the thread that is waiting for a message to get a SocketTimeoutException if it waits for longer than the timeout.
To answer your actual question:
There isn't a builtin method that one method can call to see how long another thread has been waiting for a message.
Building a separate timekeeper is possible but rather heavy-weight

Can I access another thread's resources in Java from a different thread?

I have a situation where I want to access threads in Waiting or Blocked state and destroy their connections to an external Server. Is this possible without making a global variable that stores those connections? Can I access those connection objects from another Thread in Java?
To be more specific:
I had connections with a RabbitMQ Server which throttles connections when it reaches a particular memory threshold which in my case it has reached. So, the client hangs waiting for RabbitMQ server to unblock it which would never happen in my use case. So, I want to close those particular connections. I have tried sending interrupts to those threads but it seems like those threads are not recognizing interrupts and remain hanged indefinitely.
Resources do not belong to threads, Java doesn't care which thread has a reference to a Socket object for example.
You'll need a central ConcurrentHashMap<Thread, Socket> or something like that to make your connection objects visible to the outside. Or you can interrupt threads and let them kill the connection, since almost all things wait / blocking do throw InterruptedExceptions when you do so.
So in case you know which thread it is, it's typically something like
Socket socket = connectionMap.get(thread);
socket.close();
or
thread.interrupt();
which would go together with thread code like
Thread myThread = Thread.currentThread();
connect();
while(!myThread.isInterrupted()) {
try {
doStuff();
} catch (InterruptedException e) {
myThread.interrupt(); // exception does not set interrupted state
}
}
disconnect();

How can 2 threads communicate each other?

Thread A is summing up data passed from 10 clients.
while(true){
Socket clientfd= server.accept ();
BufferedReader message = new BufferedReader(new InputStreamReader (clientfd.getInputStream() ) );
String val = message.readLine();
this.sum_data+=(message.readLine();
message.close ();
clientfd.close ();
this.left--;
if(this.left==0){
System.out.println(this.sum_data);
break;
}
}
Thread B is constantly communicating with clients whether they are alive or not (heartbeating technique).
The thing is that clients sometimes can fail, and in that case, thread which is summing up data should just print out the all possible results from alive clients. Otherwise, it will never printout the result.
So, if heartbeat thread notices one client is not responding, is there a way for it to tell the other thread (or change other thread's class variable this.left)?
Basically, there are two general approaches to thread communication:
Shared memory
Event/queue based
In the shared memory approach, you might create a a synchronized list or a synchronized map that both threads may read from and write to. Typically there is some overhead to making sure reads and writes occur without conflicts, you don't want to have an object you're reading deleted while you're reading it, for instance. Java provides collections which are well behaved, like Collections.synchronizedMap and Collections.synchronizedList.
In event, or queue based, thread communication, threads have incoming queues and write to other thread's incoming queues. In this scenario, you might have the heartbeat thread load up a queue with clients to read from, and have the other thread poll/take from this queue and do its processing. The heartbeat thread could continually add the clients that are alive to this queue so that the processing thread "knows" to continue processing them.

Efficiency of while(true) ServerSocket Listen

I am wondering if a typical while(true) ServerSocket listen loop takes an entire core to wait and accept a client connection (Even when implementing runnable and using Thread .start())
I am implementing a type of distributed computing cluster and each computer needs every core it has for computation. A Master node needs to communicate with these computers (invoking static methods that modify the algorithm's functioning).
The reason I need to use sockets is due to the cross platform / cross language capabilities. In some cases, PHP will be invoking these java static methods.
I used a java profiler (YourKit) and I can see my running ServerSocket listen thread and it never sleeps and it's always running. Is there a better approach to do what I want? Or, will the performance hit be negligible?
Please, feel free to offer any suggestion if you can think of a better way (I've tried RMI, but it isn't supported cross-language.
Thanks everyone
If you mean something like this:
while (true) {
Socket socket = server.accept();
/* Do something with socket... */
}
then, no, the call to accept() does not "take an entire core." It's a blocking call that will allow the CPU to be scheduled for another thread until a client actually connects. Once the call to accept() returns, the current thread will be scheduled to run and will consume CPU until it blocks on accept() in the next iteration of the loop.
To avoid the listen backlog of other clients growing too large, another thread usually handles interaction with the newly-accepted Socket, leaving one thread to focus on accepting new clients. The socket handling thread might handle many sockets, using NIO, or it might be dedicated to a single socket, which is much simpler to code but won't scale well past many hundreds of simultaneous connections.
You might want to take a look at the Java 1.4 nio libraries and in particular ServerSocketChannel. I use this very successfully to implement an efficient server, the key bits of code are:
Selector selector = Selector.open();
ServerSocketChannel server= ServerSocketChannel.open();
server.socket().bind(new java.net.InetSocketAddress(port));
server.configureBlocking(false);
SelectionKey serverKey = server.register(selector, SelectionKey.OP_ACCEPT);
// start listening thread
new Thread(listener).start();
And the listener is just a loop that runs:
selector.select(1000); // listen for one second max
Set<SelectionKey> keys = selector.selectedKeys();
if (keys.size()>0) {
handleKeys(keys);
}
I used a java profiler (YourKit) and I can see my running ServerSocket listen thread and it never sleeps and it's always running.
Basically, the profiler is misleading you.
I assume your code looks like this:
ServerSocket server = ...
// configure server socket
try {
while (true) {
Socket socket = server.accept();
// do something with socket (and close it afterwards!)
}
} catch (InterruptedException ex) {
// we're outta here!
}
This will not consume significant CPU ... unless you have done something pathological, like calling ServerSocket.setSoTimeout(int) with a small timeout.
Let the core sleep a little. In your Runnable method, add something like
Thread.sleep(250); // milliseconds
in every loop.
That should significantly reduce CPU usage
Edit: bad idea, see comments, sorry, my fault
And: don't use while(true). it's awful design, as the semantics suggest that eventually true will not be true anymore. Usually you will want to query some volatile or atomic variable from the main thread
public class MyClass {
class MyRunnable implements Runnable {
public void run() {
while (MyClass.this.keepGoing.get()) {
// listen();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// deal with exception
}
}
}
}
private final AtomicBoolean keepGoing = new AtomicBoolean(true);
}
That way the main thread has a way to stop the listener thread.

Categories

Resources