I am trying to synchronize a file cashing on the hard disk from the database.
What i am doing in checking if the file exists and if not i fetch the file from the database and deploy it. I would not like to write the file multiple times due to a Race condition.
Here is the code i made:
IMPORTENT: This code is inside a Bean with all its meanings
@Override public String getThumbnailPictureUrl(Design design) { String relativePath = String.format(THUMBNAIL_URL, design.getId(), design.getThumbnailPicture().getFileName()); String realPath = servletContext.getRealPath("/"+relativePath); logger.info("Request Thumbnail picture for design: " + design.getId()); logger.info("Thumbnail picture relative path: " + relativePath); logger.info("Thumbnail picture real path: " + realPath); File file = new File(realPath); if(!file.exists()) { synchronized (thumbnailLock) { if(!file.exists()) { logger.warn("Could not fild file in path: " + realPath); FileAttachment pictureAttachment = design.getThumbnailPicture(); Hibernate.initialize(pictureAttachment.getAttachment()); Data data = (Data) pictureAttachment.getAttachment(); file = toolBox.convertBlobToFile(data.getBlob(), file); logger.warn("file created in path: " + realPath); } } } return relativePath; }
With this solution in case i don't find the file i really wont write the file 2 times as well as any other file as i am synchronizing the entire block for all threads trying to reach it even if is to write a different file.
Any suggestions?
Thanks.
Synchronization in java is the capability to control the access of multiple threads to any shared resource. In the Multithreading concept, multiple threads try to access the shared resources at a time to produce inconsistent results. The synchronization is necessary for reliable communication between threads.
Synchronization can result in hold-wait deadlock where two threads each have the lock of an object, and are trying to acquire the lock of the other thread's object. Synchronization must also be global for a class, and an easy mistake to make is to forget to synchronize a method.
A synchronized block in Java is synchronized on some object. All synchronized blocks synchronize on the same object can only have one thread executing inside them at a time. All other threads attempting to enter the synchronized block are blocked until the thread inside the synchronized block exits the block.
Similar to @Avi's solution but using a ConcurrentHashMap.
private final ConcurrentMap<String, Object> map = new ConcurrentHashMap<>();
String name = file.getName();
Object lock = map.get(name);
if (lock == null) {
map.putIfAbsent(name, new Object());
lock = map.get(name);
}
synchronized (lock) {
// do something
}
map.remove(name);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With