Synchronized in a Java thread - java

My program is a client connected to multiple servers. I save connection objects to all servers in a static map object:
server1 -> connection1
server2 -> connection2
serverN -> connectionN
public class CacheConnection {
private final static Map cacheConnection = new HashMap();
public static void add(String serverName, Socket sock) {
synchronized (cacheConnection) {
cacheConnection.put(serverName, sock);
}
}
public static Socket get(String serverName) {
return (Socket) cacheConnection.get(serverName);
}
..
}
I have many threads getting connections from this map to communicate with the servers. How can I ensure a connection can only be used by one thread at a time?
For example, I want to be sure thread 1 and thread 2 cannot use connection 1 at the same time.

I am not completely sure, what you want. I assume that you want to guarantee that only one thread at a time accesses one particular server.
If your connection is something like a socket, then you can use it as a lock in a synchronization statement:
private void send(Connection c, Data d) {
synchronized (c) {
// for each connection object, only one thread may be inside this block.
// all other threads wait until the thread currently in this block exits it.
c.send(d);
}
}
// somewhere else ...
Data data = determineDataToSend()
Connection connection = map.get(key);
send(connection, data)
You can put the logic also into a decorator for the connection. This is especially useful if your connection has more than one method that send or receive (e.g., because you use a higher abstraction level like RMI):
public interface PowerfulConnection {
public void doA();
public int doB(ParameterForB param);
}
public class ConnectionImpl implements PowerfulConnection {
// handles the actual connection
}
/**
* This method is a decorator for PowerfulConnection that synchronizes all method accesses.
*/
public class SynchronizedConnection implements PowerfulConnection {
private PowerfulConnection target;
public SynchronizedConnection(PowerfulConnection target) {
if (target == null) throw new NullPointerException();
this.target = target;
}
public synchronized void doA() {
target.doA();
}
public synchronized int doB(ParameterForB param) {
return target.doB(param);
}
}
If you are using the decorator approach, then the only thing you need to change is the instance creation. Instead of:
private void connect(key, connectionParams) {
map.put(key, new ConnectionImpl(connectionParams));
}
use
private void connect(key, connectionParams) {
map.put(key, new SynchronizedConnection(new ConnectionImpl(connectionParams)));
}

Or, in your initial example, the get method could just remove the connection from the map. Of course, that means the client would have to be sure (probably in a finally block, to call add again, when done)
Then have wait and notify loops for when a client comes in to ask for a connection, and it's not there.

Related

Asynchronous update of promise in Netty Nio

I have got a server and client architecture that exchange information. I want to return from the server the number of connected channels. I want to return the message of the server to the clients using promise. My code is:
public static void callBack () throws Exception{
String host = "localhost";
int port = 8080;
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(), new ClientHandler(promise));
}
});
ChannelFuture f = b.connect(host, port).sync();
//f.channel().closeFuture().sync();
}
finally {
//workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
callBack();
while (true) {
Object msg = promise.get();
System.out.println("The number if the connected clients is not two");
int ret = Integer.parseInt(msg.toString());
if (ret == 2){
break;
}
}
System.out.println("The number if the connected clients is two");
}
When I run one client it is always receiving the message The number if the connected clients is not two and the returning number is always one. When I run a second client it is receiving always as a returning value two, however, the first client still is receiving one. I cannot find which is the correct way to update the promise for the case of the first client.
EDIT:
Client Server:
public class ClientHandler extends ChannelInboundHandlerAdapter {
public final Promise<Object> promise;
public ClientHandler(Promise<Object> promise) {
this.promise = promise;
}
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
RequestData msg = new RequestData();
msg.setIntValue(123);
msg.setStringValue("all work and no play makes jack a dull boy");
ctx.writeAndFlush(msg);
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println(msg);
promise.trySuccess(msg);
}
}
The code from the client handler storing the message received from server to the promise.
With the Netty framework, a Promise and a Future are write-once objects, this principle makes them easier to use in a multithreaded environment.
Since a Promise doesn't do what you want, we need to see if other technologies are fit for your conditions, your conditions basically boil down to:
Read from multiple threads
Write from a single thread only (as inside a Netty channel the read method can only be executed by 1 thread at the same time, unless the channel is marked shareable)
For these requirements, the best fitting match is a volatile variable, as this is thread-safe for reading, and can safely be updated by 1 thread without worrying about the write order.
To update your code for usage with a volatile variable, it requires some modifications, as we cannot easily pass the reference link to the variable inside your function, but we must pass a function that updates the backend variable.
private static volatile int connectedClients = 0;
public static void callBack () throws Exception{
//....
ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(),
new ClientHandler(i -> {connectedClients = i;});
//....
}
public static void main(String[] args) throws Exception {
callBack();
while (true) {
System.out.println("The number if the connected clients is not two");
int ret = connectedClients;
if (ret == 2){
break;
}
}
System.out.println("The number if the connected clients is two");
}
public class ClientHandler extends ChannelInboundHandlerAdapter {
public final IntConsumer update;
public ClientHandler(IntConsumer update) {
this.update = update;
}
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
RequestData msg = new RequestData();
msg.setIntValue(123);
msg.setStringValue("all work and no play makes jack a dull boy");
ctx.writeAndFlush(msg);
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println(msg);
update.accept(Integer.parseInt(msg));
}
}
While the approach above should work, we quickly see that the while loop inside the main class uses a large share of CPU time, and this may affect other parts of your local client system, luckily, this problem is also solvable if we add other parts to the system, namely synchronization. By leaving the initial read of the connectedClients outside the synchronization block, we can still profit from the quick reads in the case of the "true" case, and in case of the "false' case, we can safe important CPU cycles that can be used in other parts of your system.
To tackle this problem, we use the following steps when reading:
Store the value of connectedClients in a separate variable
Compare this variable with the target value
If it's true, then break early out of the loop
If false, go inside a synchronized block
start a while true loop
Read out the variable again, since the value might be changed now
Check the condition, and break if condition is correct now
If not, wait for a change in the value
And the following when writing:
synchronize
Update the value
Wake up all other threads waiting for this value
This can be implemented in code as the following:
private static volatile int connectedClients = 0;
private static final Object lock = new Object();
public static void callBack () throws Exception{
//....
ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(),
new ClientHandler(i -> {
synchronized (lock) {
connectedClients = i;
lock.notifyAll();
}
});
//....
}
public static void main(String[] args) throws Exception {
callBack();
int connected = connectedClients;
if (connected != 2) {
System.out.println("The number if the connected clients is not two before locking");
synchronized (lock) {
while (true) {
connected = connectedClients;
if (connected == 2)
break;
System.out.println("The number if the connected clients is not two");
lock.wait();
}
}
}
System.out.println("The number if the connected clients is two: " + connected );
}
Server side changes
However, not all of your problems are related to the client side.
SInce you posted a link to your github repository, you never send a request from the server back to the old clients when a new person has joined. Because this is not done, the client is never notified about the change, make sure to do this as well.

Multithreaded Java worker with a size restricted resource pool

I have this 'Worker' class, which uses a resource 'Client'.
There may be any number of threads, running the 'Worker' at any given time.
The 'Client' is not thread-safe, thus I'm using 'ThreadLocal' for it.
The 'Client' connects to some server and executes a HTTP 'Request' that the worker feeds the 'Client'.
public class Worker {
// Client is NOT thread-safe !!!
private static ThreadLocal<Client> client = new ThreadLocal<Client>();
#Override
protected void onGet(Request req) {
handleRequest(req);
}
private void handleRequest(Request req) {
someRunnableExecutor(new Runnable() {
#Override
public void run() {
get_client().send_req(req);
}
});
}
private Client get_client() {
Client c = client.get();
if (c == null) {
c = new Client();
client.set(c);
}
return c;
}
At the current implementation (above), stripped down for clarity, there are as many "active" 'Clients' as there are running 'Workers'.
This is a problem because the server is being exhausted.
What I can do is only fix the 'Worker'. Have no access to the 'Client', server or the executor that runs the workers.
What I want to do is to have a Queue of 'Client'(s) and a piece of a synchronized code, in the 'Worker', that takes a 'Client' off the Queue, if the Queue is empty the 'Worker' should wait till there is one in the Queue for him to take. Then put the 'Client' back into the Queue - synchronized as well.
I really want to keep it as simple as possible, with the possible minimum changes made to the code.
No new classes, no factories, just some data structure to hold the 'Client'(s) and synchronization.
I am a bit puzzled with how to achieve that generally, as well as by the fact that the 'Client' is not thread-safe and that I have to 'ThreadLocal'(ize) it. Is this how do I put that in a Queue?
private static Queue<ThreadLocal<CLient>> queue =
new LinkedList<ThreadLocal<CLient>>();
Also, how/where do I initialize that Queue, once, with say 5 clients?
Please share your thoughts.
You don't need ThreadLocal here, as you want to have less Clients than Workers. All you need in BlockingQueue.
Notice! I supposed that Client's send_req is synchronous, if it's not - the code needs some changes in run() method
public class Worker {
private static final int CLIENTS_NUMBER = 5;
private static final BlockingQueue<Client> queue = new LinkedBlockingQueue<>(CLIENTS_NUMBER);
static {
for (int i = 0; i < CLIENTS_NUMBER; i++)
queue.put(new Client());
}
#Override
protected void onGet(Request req) {
handleRequest(req);
}
private void handleRequest(Request req) {
someRunnableExecutor(new Runnable() {
#Override
public void run() {
try {
Client client = takeClient();
client.send_req(req);
putClient(client);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
}
private Client takeClient() throws InterruptedException {
return queue.take();
}
private void putClient(Client client) throws InterruptedException {
queue.put(client);
}
}

What is the scope of "this" when calling a method from an individual thread?

I am writing a small Java class to act a heartbeat for a project. The class is fairly simple. I have a public class called HeartbeatServer.class that contains to private classes which both implement Runnable.
The heartbeat and listener thread will both use the same DatagramSocket which I created outside of the scope of both thread classes and declared it volatile so both threads can access it.
My question is regarding my thread classes. In the thread classes if I call HeartbeatServer.this.serverSocket what is the scope of this? My concern is I don't want each thread to use a different version of HeartbeatServer since I have to bind the DatagramSocket to a specific IP address and port.
Is what I am doing correct to get the result I am looking for? I want both threads to have access to the same DatagramSocket that was created by the constructor of the HeartbeatServer class.
Here is my code.
public volatile DatagramSocket serverSocket;
private Map<String, InetSocketAddress> registeredClients = new HashMap<String, InetSocketAddress>();
public volatile Boolean running = true;
public HeartbeatServer() throws SocketException{
serverSocket = new DatagramSocket(null);
}
** Other methods would go here **
// This is the thread that will send the heartbeats back to the client.
private class HeartbeatThread implements Runnable {
#Override
public void run() {
while (HeartbeatServer.this.running) {
HeartbeatServer.this.sendData();
}
}
}
// This is the thread that will listen for clients connecting to the server.
private class ListenerThread implements Runnable {
#Override
public void run() {
while (HeartbeatServer.this.running) {
HeartbeatServer.this.recieveData();
}
}
}
** NOTE **
My code is not done, so things might not make any sense in the current context.
If you need HeartbeatServer to be unique you should make the HeartbeatServer Singleton. Please check here for more details.
Simply
public class HeartbeatServer {
private static HeartbeatServer heartbeatServer;
// Disable object creation from other classes
private HeartbeatServer () {
}
public static HeartbeatServer getInstance() {
if(heartbeatServer == null)
heartbeatServer = new HeartbeatServer();
return heartbeatServer;
}
}
What you are doing is, your thread object is using the enclosing parent. Which is not recommended.
If you want to make sure the HeartBeatServer instance you get is the right one, you could add a constructor to the internal runnables, along the lines of
private class HeartbeatThread implements Runnable {
private HeartbeatServer server;
HeartBeatThread(HeartbeatServer theServer) {
this.server = theServer;
}
#Override
public void run() {
while (server.running) {
server.sendData();
}
}
}

Efficiently awaiting for resources

I wonder what would be the most efficient solution to this problem.
I have a multithreaded database implementation (LevelDB, for example) and I want it to handle synchronization, since it can do it better. However, I want to initialize the database asynchronously, without blocking any thread unless they somehow want to use the database before it has been opened.
Something along the lines of:
public class Storage {
Database db;
public Storage() {
open();
}
private void open() {
new Thread(new Runnable() {
public void run() {
// attempt to open db here, i.e. change the value of Storage.db from null
// into Object
}
}).run();
}
public void accessMethod() {
// this method should only use a non-null Storage.db value, it should block
// until the thread above does not set the value of db to be an Object
}
public void nonAccessMethod() {
// this method is not concerned with the value inside Storage.db and should not
// block while the thread above is running
// example: memory cached operations on the db which will be executed after
// the thread above finishes and "unlocks" Storage.db
}
}
I came up with this solution, but it is not very efficient:
public class Storage {
ReentrantLock lock;
Database db;
public Storage() {
lock = new ReentrantLock();
open();
}
private void open() {
lock.lock(); // to be released in thread below
new Thread(new Runnable() {
public void run() {
// heavy work here while populating Storage.db
lock.unlock();
}
}).run();
}
// returns true if the database is not yet open and that we need to release
// the lock once our code segment completes
private boolean blockIfNotOpen() {
if (lock.tryLock()) {
lock.unlock(); // << this code segment sucks
return false;
} else {
lock.lock();
return true;
}
}
public void accessMethod() {
boolean wasNotOpen = blockIfNotOpen();
// "blocking" code here
if (wasNotOpen) {
lock.unlock();
}
}
public void nonAccessMethod() {
// not concerned with Storage.db and therefore not trying to lock
}
}
I don't like this solution because it still synchronizes access to the database in the implementation of Storage long after Storage.db has been populated, when in fact there is an underlying system inside DB which can handle concurrency better (example: DB exposes worker threads, etc.).
Synchronizing on the Storage object is not a solution since it will, well synchronize, all the time, instead of only when Storage.db is null.
Notes: I'm guaranteed that there will be no concurrent calls before Storage's constructor finishes, if you're worried about the lock. :) So, all concurrency happens after the constructor.
I think the solution would be using ReadWriteLock - writeLock().lock() in constructor, writeLock().unlock() after the db is initialized and the readLock() is used from the db consumers.
Another option, use Future:
public class Storage {
private final Future<Database> dbFuture = Executors.newSingleThreadExecutor().submit(
new Callable<Database>()
{
public Database call()
{
return new Database(...);//Long running DB initialisation
}
}
);
public void accessMethod()
{
Database db = dbFuture.get();// will wait while the call() is not completed yet.
}
}

How to wrap a callable in a type-friendly way?

I'm trying to implement a work queue in Java that limits the amount of work that can be taken at a time. In particular, it is trying to protect access to an external resource. My current approach is to use a Semaphore and a BlockingQueue so that I have something like this:
interface LimitingQueue<V> {
void put(Callable<V> work);
Callable<V> tryPoll();
}
It should behave like this:
#Test
public void workLimit() throws Exception {
final int workQueue = 2;
final LimitingQueue<Void> queue = new LimitingQueue<Void>(workQueue);
queue.put(new Work()); // Work is a Callable<Void> that just returns null.
queue.put(new Work());
// Verify that if we take out one piece of work, we don't get additional work.
Callable<Void> work = queue.tryPoll();
assertNotNull(work, "Queue should return work if none outstanding");
assertNull(queue.tryPoll(), "Queue should not return work if some outstanding");
// But we do after we complete the work.
work.call();
assertNotNull(queue.tryPoll(), "Queue should return work after outstanding work completed");
}
The implementation of tryPoll() uses Semaphore#tryAcquire and, if successful, creates an anonymous Callable that wraps the Semaphore#release call in a try/finally block around the call to work.call().
This works, but is somewhat unsatisfying in that if the user of this class puts work that is of some specific class that implements Callable, the user does not get access to that class back when looking at the result of tryPoll. Notably, tryPoll() returns a Callable<Void>, not a Work.
Is there a way to achieve what the work limitation effect while giving the caller back a usable reference to the work object that was submitted? (It's fine to strengthen the type signature of LimitingQueue to be more like LimitingQueue<R, T extends Callable<R>>.) I can't think of a way to ensure that the semaphore is released after calling the work item without doing this kind of wrapping.
EDIT2 I have replaced what was here with a suggestion on how to implement what you're looking for. Let me know if you want some of the old info back and I can restore it.
public class MyQueue<T> {
private Semaphore semaphore;
public void put(Work<T> w) {
w.setQueue(this);
}
public Work<T> tryPoll() {
return null;
}
public abstract static class Work<T> implements Callable<T> {
private MyQueue<T> queue;
private void setQueue(MyQueue<T> queue) {
if(queue != null) {
throw new IllegalStateException("Cannot add a Work object to multiple Queues!");
}
this.queue = queue;
}
#Override
public final T call() throws Exception {
try {
return callImpl();
} finally {
queue.semaphore.release();
}
}
protected abstract T callImpl() throws Exception;
}
}
Then use it like thus:
public class Test {
public static void main(String[] args) {
MyQueue<Integer> queue = new MyQueue<Integer>();
MyQueue.Work<Integer> work = new MyQueue.Work<Integer>() {
#Override
protected Integer callImpl() {
return 5;
}
};
queue.put(work);
MyQueue.Work<Integer> sameWork = queue.tryPoll();
}
}
Sounds to me like you should just use the builtin ExecutorService. Use Executors#newCachedThreadPool to get a pool, then submit Callable jobs which return back a Future.

Categories