Reputation: 9935
I have been developing a multithreading web application using Spring mvc + Hibernate with redis for cache storage. I'm looking at finding a way to apply locks to controllers or services.
I can't make use of the locking mechanisms provided by Hibernate as it's meant to be applied at database level.
Here's an example:
@RestController
@RequestMapping(RestConstants.BASE_PATH + "/campaigns")
Class CampaignController {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ApiResponse<?> findOne(@PathVariable Integer id) {
Campaign campaign = repo.findOne(id);
return toResponse(campaign);
}
@RequestMapping(value = "", method = RequestMethod.POST)
public create(@RequestBody Campaign campaign) {
//create an campaign here
}
@RequestMapping(value = "/{id}", method = RequestMethod.PATCH)
public update(@RequestBody Campaign campaign) {
//update an campaign here
}
}
@RestController
@RequestMapping(RestConstants.BASE_PATH + "/bulkCampaigns")
Class CampaignBulkController {
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public create(@RequestPart MultipartFile data) {
/*
Data contains a list of campaigns with their details,
controller will iterate through the list and create all the campaigns.
*/
}
}
While requests mapped to create method in CampaignBulkController is being processed, all the other writes on campaigns cannot be handled but reads are allowed.That is, requests to update or create campaign/campaigns should be dropped.
There are multiple servers and each server is multi-threaded.
I'm new to Spring and Hibernate, any idea or suggestions would be appreciated!
Upvotes: 0
Views: 2706
Reputation: 73578
I'm going to outline an initial answer here, possibly for later modification.
If you use a shared ReadWriteLock and use read locks for the regular operations, you can have your privileged operations use write locks to block the regular operations.
// Regular operation tries to lock, if not successful a privileged operation is happening
if(!lock.readLock().tryLock())
return cannotProcessResponse;
performRegularOperation();
lock.readLock().unlock();
// Privileged operation always waits for lock
lock.writeLock().lock();
performPrivilegedOperation();
lock.writeLock().unlock();
Now there are some issues with this approach. If using a single shared lock, only one privileged operation can run at a time. If this is an issue, multiple locks can be used and their read locks locked together (this can be deadlock prone, so care must be taken). Lock fairness should also be considered.
Upvotes: 1