Reputation: 1038
my problem is I want a user based lock that I am able to create in one thread and release in a different thread. I was trying to use reetrant locks but my idea is falling short somewhere.
I.e. There are blue, green and purple people. Each color group only has one shovel. If the purple group needs to use the shovel they need to wait for the shovel to be available. Both the blue group and purple group can have their respective shovels at a given moment.
Mainclass
public class MainReentrant {
public static ConcurrentHashMap<String, ReentrantLock> locks;
public static void main(String[] args){
locks = new ConcurrentHashMap<String, ReentrantLock>();
new Thread( new ReentrantEx(1)).start();;
new Thread( new ReentrantEx(1)).start();;
new Thread( new ReentrantEx(2)).start();;
}
}
The first step is to create a lock and lock it.
public class ReentrantEx implements Runnable {
private Integer id;
public ReentrantEx(Integer id){
this.id = id;
}
public void doSomethingPerUser(Integer i){
synchronized(i){
ReentrantLock tempLock = MainReentrant.locks.get(i.toString());
if(tempLock != null){
//we have an unlocked lock
tempLock.lock();
}else{
//add a new lock for this customer
tempLock = new ReentrantLock();
tempLock.lock();
MainReentrant.locks.put(i.toString(), tempLock);
}
System.out.println("doSomethingPerUser lock should be held : " + i);
new Thread(new RandomRunnable(i)).start();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
doSomethingPerUser(id);
}
}
next the randomRunnable class attempts to release the lock created by ReentrantEx
public class RandomRunnable implements Runnable {
private Integer id;
public RandomRunnable(Integer id){
this.id = id;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(" RandomRunnable: id = "+ id );
ReentrantLock tempLock = MainReentrant.locks.get(id.toString());
synchronized(tempLock){
if(tempLock == null){
System.out.println("ERROR: we have a lock that we cannot free");
return;
}else{
tempLock.unlock();
//ReentrantEx.locks.put(id.toString(), tempLock);
}
}
}
}
Whenever I do this I get these sort of errors:
Exception in thread "Thread-5" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:127)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1239)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:431)
at test.RandomRunnable.run(RandomRunnable.java:25)
at java.lang.Thread.run(Thread.java:695)
here is a good link on the locks in general... locks
Upvotes: 1
Views: 1519
Reputation: 200296
Simply put, ReentrantLock
is not for you. The subject acquring the lock is a thread, so when you attempt to release it in another thread, that thread is actually trying to release a lock it doesn't own. Meanwhile the thread that did acquire it, keeps holding on to it.
What you probably need instead is a Semaphore
—more specifically, a collection of semaphores, one for each color group.
Upvotes: 4