Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to synchronize a file writing system in java

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.

like image 473
Gleeb Avatar asked Jul 09 '13 23:07

Gleeb


People also ask

Can we synchronize process in Java?

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.

What is the problem with synchronization in Java?

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.

How does synchronize work in Java?

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.


1 Answers

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); 
like image 131
Peter Lawrey Avatar answered Oct 11 '22 23:10

Peter Lawrey