Java在一个线程中锁定,在另一个线程中解锁

Java在一个线程中锁定,在另一个线程中解锁,java,multithreading,Java,Multithreading,我需要锁定类对象(处理套接字连接)并将这些对象传递给线程进行处理 public class Client{ protected Socket socket; ... public Lock lock = new ReentrantLock(); } 我有一个简单的worker类来处理这项工作 public class ClientWriterWorker extends Runnable{ protected Client client; prot

我需要锁定类对象(处理套接字连接)并将这些对象传递给线程进行处理

public class Client{

    protected Socket socket;
    ...
    public Lock lock = new ReentrantLock();

}
我有一个简单的worker类来处理这项工作

public class ClientWriterWorker extends Runnable{

    protected Client client;
    protected String data;

    public ClientWriterWorker(Client client, String data){
        this.client = client;
        this.data = data;
    }

    @Override
    public void run(){
        // do the processing
        this.client.write(this.data);
        // release the lock?
        this.client.lock.unlock(); // does not work
    }

}
然后我有一个循环,它解锁客户端,锁定它,并将它传递给线程

Client currentClient = null;
while(true){
    for(Client client : clients){
        if(client.lock.tryLock()){
             // we have the lock
             currentClient = client;
             break;
        }
    }
    if(currentClient != null){
        break;
    }
}
new Thread(new ClientWriterWorker(currentClient, "some data")).start();

可以解锁另一个线程中的锁吗?我的设计有缺陷吗?

的行为规范指定必须由锁定它的线程解锁它。这是有意义的,因为这个锁实现的全部目的是跟踪哪个线程锁定了它,以便它可以根据需要多次重新锁定它(重入)。引用部分文件:

试图释放此锁

如果当前线程是此锁的保持器,则保持计数将减少。如果保持计数现在为零,则释放锁。如果当前线程不是此锁的持有者,则抛出IllegalMonitorStateException


您完全可以实现自己的
Lock
类,该类可以从任何线程锁定和解锁。以下是一个部分答案:

public class MyLock implements java.util.concurrent.locks.Lock {

    private boolean isLocked = false;

    public synchronized void lock() throws InterruptedException {
        while (isLocked)
            wait();
        isLocked = true;
    }

    public synchronized void unlock() {
        if (!isLocked)
            throw new IllegalStateException();
        isLocked = false;
        notify();
    }    

}

的行为规范指定它必须由锁定它的线程解锁。这是有意义的,因为这个锁实现的全部目的是跟踪哪个线程锁定了它,以便它可以根据需要多次重新锁定它(重入)。引用部分文件:

试图释放此锁

如果当前线程是此锁的保持器,则保持计数将减少。如果保持计数现在为零,则释放锁。如果当前线程不是此锁的持有者,则抛出IllegalMonitorStateException


您完全可以实现自己的
Lock
类,该类可以从任何线程锁定和解锁。以下是一个部分答案:

public class MyLock implements java.util.concurrent.locks.Lock {

    private boolean isLocked = false;

    public synchronized void lock() throws InterruptedException {
        while (isLocked)
            wait();
        isLocked = true;
    }

    public synchronized void unlock() {
        if (!isLocked)
            throw new IllegalStateException();
        isLocked = false;
        notify();
    }    

}

为什么不直接使用监视器呢?它们能够在完成后广播/唤醒其他睡眠线程


这里有一个链接解释了如何在java中使用它们,为什么不使用监视器呢?它们能够在完成后广播/唤醒其他睡眠线程


这里有一个链接解释了如何在java中使用它们。在我看来,您应该重新思考您的问题

通常,您使用某个对象(线程、连接等)的池,每当需要某个对象时,对池提供程序对象的调用就会给出对请求对象的引用。在将该对象返回到池(通过调用解锁方法)之前,不需要进一步锁定,因为整个想法是该对象现在由从池中请求它的线程独占(并且在拥有该对象的线程返回该对象之前,池不会再次发出该对象)

在这种模式中,通常只有一个锁(针对池),通常通过在池对象(或专用锁对象)上同步来实现。唯一执行锁定和解锁的方法都可以在池中找到(获取()和释放()。托管对象本身不包含任何锁定

在最简单的版本中,它可以如下所示:

class MyResource {
     // represents the managed resources
}

class MyPool {
     private List<MyResource> available = new ArrayList<>();

     public synchronized MyResource obtain() {
         MyResource result = available.isEmpty()
             ? new MyResource() : available.remove(0);
         return result;
     }

     public synchronized void release(MyResource resource) {
         available.add(resource);
     }
}
类MyResource{
//表示托管资源
}
类MyPool{
可用的私有列表=新的ArrayList();
公共同步MyResource获取(){
MyResource result=available.isEmpty()
?新建MyResource():可用。删除(0);
返回结果;
}
公共同步的作废释放(MyResource){
可用。添加(资源);
}
}
显然,我省略了所有用于实际初始化池的代码,您可能希望以不同的方式处理没有可用资源的情况(例如,等待资源变为可用资源,而不是创建新资源)

这种方法的一种变体是让资源类有一个对其池的引用,并将release()方法移动到资源类上;这反过来调用池上的非公共方法来执行实际发布


只需稍加规划,就可以使用AtomicReference的compareAndSet()方法实现此模式的无锁版本来管理池内容,而无需在任何地方进行同步。

在我看来,您应该重新考虑您的问题

通常,您使用某个对象(线程、连接等)的池,每当需要某个对象时,对池提供程序对象的调用就会给出对请求对象的引用。在将该对象返回到池(通过调用解锁方法)之前,不需要进一步锁定,因为整个想法是该对象现在由从池中请求它的线程独占(并且在拥有该对象的线程返回该对象之前,池不会再次发出该对象)

在这种模式中,通常只有一个锁(针对池),通常通过在池对象(或专用锁对象)上同步来实现。唯一执行锁定和解锁的方法都可以在池中找到(获取()和释放()。托管对象本身不包含任何锁定

在最简单的版本中,它可以如下所示:

class MyResource {
     // represents the managed resources
}

class MyPool {
     private List<MyResource> available = new ArrayList<>();

     public synchronized MyResource obtain() {
         MyResource result = available.isEmpty()
             ? new MyResource() : available.remove(0);
         return result;
     }

     public synchronized void release(MyResource resource) {
         available.add(resource);
     }
}
类MyResource{
//表示托管资源
}
类MyPool{
可用的私有列表=新的ArrayList();
公共同步MyResource获取(){
MyResource result=available.isEmpty()
?新建MyResource():可用。删除(0);
返回结果;
}
公共同步的作废释放(MyResource){
可用。添加(资源);
}
}
显然,我省略了所有用于实际初始化池的代码,您可能希望以不同的方式处理没有可用资源的情况(例如,等待资源变为可用资源,而不是创建新资源)

th的变体
    volatile CountDownLatch latch = new CountDownLatch(1);
    
    private void commsWaitForResponse() {
        try {
            latch.await(3500, TimeUnit.MILLISECONDS);
                if (latch.getCount() < 1) {
                    //create new latch
                    latch = new CountDownLatch(1);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    private void commLockRelease() {
            latch.countDown();
        }