简体   繁体   English

Java中基于名称的可重入锁

[英]Name based Reentrant Lock in Java

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. 我试图使用Reetant锁,但是我的想法在某个地方不尽人意。

Ie 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 接下来,randomRunnable类尝试释放由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 这里是对一般的锁一个很好的链接...

Simply put, ReentrantLock is not for you. 简而言之, ReentrantLock不适合您。 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. 相反,您可能需要的是一个Semaphore -更具体地说,是一组信号灯,每个颜色组一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM