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();
}