I'm implementing a quick file server using Java RMI, which has 2 remote methods, one is for reading a file from the server and the other is for writing it to the client.
I want to lock concurrent access to same file. For example, if 10 users concurrently call read() and write() remote methods, specifying the same file: 'foo.txt', I need that the first call to be completely executed before the second call does, and the second call is completely executed before the third call does...
If I use "syncronized" statement in the two RMI methods, I lose efficiency if different users concurrently call these methods, specifying different files.
On the other hand, I can't use the FileLock class because:
"File locks are held on behalf of the entire Java virtual machine.
They are not suitable for controlling access to a file by multiple
threads within the same virtual machine."
and in RMI, there is only one process in the same JVM, that executes new threads for each remote call.
You could make use of ReadWriteLock to handle read/write locks of the Path of each file - but only if you don't run multiple processes of your RMI server or expect those files to be changed outside one RMI server VM. Each of the entry points for read or write needs to locate ReentrantReadWriteLock for the Path provided such as using getReadWriteLock(Path) here:
private static ConcurrentHashMap<Path,ReentrantReadWriteLock> LOCKS = new ConcurrentHashMap<>();
private static ReentrantReadWriteLock getReadWriteLock(Path path) {
return LOCKS.computeIfAbsent(path, p -> new ReentrantReadWriteLock());
}
Then your own code can use the readLock() or writeLock() API calls to allow multiple readers when there are no writes taking place. Over time you'd need to do some housekeeping to purge entries which are no longer in use.
Related
I have a Java program, which needs to use a function from a imported source package that loads 2GB data into the memory and use it to do the calculation.
However every time when I call the function, the loading process is processed, which is very time consuming.
My program's structure is like:
Socket Server (listening on a port)
|_ Multi Server Thread (Work as a input stream reader)
...|_ Sample Protocol (deal with the input steam using the data related functions)
I know this is a question too wide, but:
Are there any general idea that I can run the loading only once and use it to do all the calculation afterwards?
IF I import the package in the Top Level (in socket server), will that help me accelerate the loading process somehow?
What is the more common method used by the enterprise?
Since this question did not get any answer for a long time, here is
a small summary:
It turns out in the current method I used, if I load the lib in the highest level (Socket Server), we can make sure that for every thread in it we don't need to load the library again.
In the enterprise level, there are better multi-thread functions for java, like:
newCachedThreadPool()
newFixedThreadPool()
newSingleThreadExecutor()
newScheduledThreadPool()
For example we can use them like,
ExecutorService fixedThreadPool() = Executors.newFixedThreadPool(4);
Future<T> future1 = singleThreadPool.submit(new MyRunnable());
singleThreadPool.execute(new MyRunnable);
singleThreadPool.shutdown();
which might be useful in real practice.
I have a sinlgeton object which holds one method, which is NOT synchronized. The singleton can be accessed by many clients at a time - what will happen if multiple clients access that object ?
Actually I want to write a log in a single file using that method.
I guess by clients, you mean threads. Assuming you have implemented singleton correctly, all threads would be using the same instance. Since this is a method that changes state (writing to a file), it would require in general require some sort of synchronization. Although it depends on some factors - for example, if your method writes just a single line in a single call to BufferedWriter.write(), it is fine. Because BufferefWriter.write() does synchronization internally. However, if you write multiple lines or make multiple calls to BufferedWriter.write(), the different calls might execute out of order.
Now, if by clients you mean different processes, simple synchronization of course will not help. You can use FileLock to lock the file if the processes are in the same JVM. Otherwise, you have to lock using something external, such as use another temp file as lock. It depends on the OS though if it provides atomic file creates.
Are methods Files.createFile() and Files.delete() thread safe? I have read in documentation that createFile() always an atomic operation but delete() is not. Should I somehow synchronize these blocks in my Java application and how? What atomic operation means for multihreading task?
a. What atomic operation means for multihreading task?
In context of multi-threading atomicity is the ability of a thread to execute a task in such a manner so that other threads have apparently no side-effect over the state varibles of that task when it was being executed by this thread.
File.createNewFile() :- For this method the state is existence or non existence of the file, when the thread was about to execute this method. Lets say that when this method was being executed by the thread the file did not exist. Now lets say that this method takes 5 ms of time to execute and create the file. So according to the concept of Atomicity no other thread should be able to create the same file(which was not existing before) during these 5ms otherwise the very first assumption of this thread about the state of the file will change and hence the output.
So in this case the executing thread does-this by obtaining a write lock over the directory where file is to be created.
Files.delete():- The Java doc for this method says
this method may not be atomic with respect to
other file system operations. If the file is a symbolic link, then the
symbolic link itself, not the final target of the link, is deleted.
the above statement says that this operation is also atomic but in case if this method is invoked on a symbolic link, the link is deleted and not the file. Which implies that the original file exists and file system operations on that file are feasible by other threads.
to determine if a file is a symlink see the reference:-
determine symlink
b. Should I somehow synchronize these blocks in my Java application and how?
You need not handle any multi-threading scenarios in both the cases.
However you can use the method mentioned in the link above to determine symlinks and handle that separately as you would wish.
But no synchronization is required from your end for sure.
Do you mean File.createNewFile()?
Javadoc says:
The check for the existence of the file and the creation of the file if it does not exist are a single operation that is atomic with respect to all other filesystem activities that might affect the file.
With other words, between the check if the file exist and the creation of the file will be no other file operation, changing the existence of the file.
If two threads want to create the same non existing file, only one will create the file and return true. The other thread will return false.
Usually you dont need to synchronize these operations but do a proper exception handling. Maybe other programs operate on your files too.
I have three services in my Android app that are fired by two broadcast receivers. The first two write onto a file and are fired by one broadcast receiver so I can make sure that they are executed one after the other (via Context.sendOrderedBroadcast()). The third one is on its own and is fired by a separate broadcast receiver, but reads from the same file that the first two write on.
Because the broadcast receivers may be fired at the same time or nearly the same time as each other, the file might also be accessed concurrently. How can I prevent that from happening? I want to be able to either read first then write or write then read. I'm just not sure if this problem is similar to Java concurrency in general because android services, if I'm not mistaken, are an entirely different beast.
One solution would be to have your writing tasks create an empty temporary file (say .lock) before accessing the shared file and delete that same temporary file once they are done.
Your reading task can check whether .lock file exists or not.
Alternatively, you can use a FileLock.
http://developer.android.com/reference/android/app/Service.html
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work.
I suggest to read from/write to file in separate thread. You can use Only one thread at a time! for doing it in the same thread.
First of all, I shouldn't have done the file I/O in the main UI thread which is the case with Services. It should be done in another thread, like an AsyncTask.
Secondly, the ReentrantLock method is so much easier. When locked, it tells the other threads accessing the same resource to wait, and proceed only when the lock has been released. Simply instantiate a new ReentrantLock() and share that lock among the methods that read to or write from the file. It's as easy as calling lock() and unlock() on the ReentrantLock as you need it.
I have the following protobuf msg defined:
message Counts {
repeated int32 counts = 1;
}
which is shared between threads R and W as a builder:
private final Counts.Builder countsBuilder;
Thread R will only read from countsBuilder and W will only write to countsBuilder.
The shared builder will be read, written-to and (at some point) built & sent over the network.
AFAIK, concurrent reads to messages are fine, but anything else must be synchronized at a higher level by the developer? So, I can't actually write and read to the shared builder at the same time?
If this is not inherently thread-safe, I'm thinking of using some kind of thread-safe Collection<Integer> which I'll use for reading/writing and will (at some point) create a brand new message right before sending it over the network. Or am I missing something?
Thanks!
EDIT 1: I'm using protobuf 2.4.1 and java 6
EDIT 2: Some terminology and spelling fixes.
You should be fine if you synchronize both your read and writes:
synchronized (countsBuilder) {
// modify countsBuilder
}
But remember that you also need to make sure that there aren't any race conditions when building the message; the writer thread is not allowed to make any writes after the message has been built.
according to https://developers.google.com/protocol-buffers/docs/reference/cpp It's not thread-safe in C++.
And Also not in java https://developers.google.com/protocol-buffers/docs/reference/java-generated
I encountered this problem recently, And I found this. Here is what it said on C++
A note on thread-safety:
Thread-safety in the Protocol Buffer library follows a simple rule: unless explicitly noted otherwise, it is always safe to use an object from multiple threads simultaneously as long as the object is declared const in all threads (or, it is only used in ways that would be allowed if it were declared const). However, if an object is accessed in one thread in a way that would not be allowed if it were const, then it is not safe to access that object in any other thread simultaneously.
Put simply, read-only access to an object can happen in multiple threads simultaneously, but write access can only happen in a single thread at a time.
Said on java:
Note that builders are not thread-safe, so Java synchronization should be used whenever it is necessary for multiple different threads to be modifying the contents of a single builder.