Java 分层死锁(带依赖项),…或:如何获取我的";“等等”;s、 ";“通知”;s、 设计对吗? //多个服务器实例(副本),使用MsgCoordinationService进行协调 公共类服务器{ ConcurrentHashMap本地\u注册表=新建。。。 MsgCoordinationService coordination\u service=new。。 ... //要与客户端通信的套接字实例。。。 公共无效接受(套接字){ 新线程(新工作线程)).start(); } //向协调服务部门提出消息,在本地注册中心登记响应客户的需求 公众未来登记册(Msg m){ FutureMsg f=new MsgFuture();//未来句柄w.对空Msg对象的引用[=response] TxID uniqueID=协调_服务.建议;//事务ID 本地注册。添加(uniqueID,f); 返回f; } //由协调服务部呼叫,保证msg交付的全球订单 公共同步无效交付(TxID,Msg m){ …处理消息对象[请求] …如果本地注册表包含(id),“编译”响应 (当设置了某个消息标志时,使用FutureMsg f,f.get()-f.isDone()中的消息对象) ___现在: …通知正在等待的“工作者”线程检查其“未来”对象是否为一个() } 私有类Worker实现了Runnable{ ... 公开募捐{ ... Future f=Server.this.register(请求);//通过套接字s获得 而(!f.isDone()) 等待(); response=f.get(); ... } } }
我正在实现一个复制服务[多个服务器、客户端与单个服务器实例通信、创建/更新/删除操作将通过一个协调服务进行分发,该服务保证消息传递的全局顺序] 一旦客户端与服务器实例建立了新连接,所有通信都通过专用的Java 分层死锁(带依赖项),…或:如何获取我的";“等等”;s、 ";“通知”;s、 设计对吗? //多个服务器实例(副本),使用MsgCoordinationService进行协调 公共类服务器{ ConcurrentHashMap本地\u注册表=新建。。。 MsgCoordinationService coordination\u service=new。。 ... //要与客户端通信的套接字实例。。。 公共无效接受(套接字){ 新线程(新工作线程)).start(); } //向协调服务部门提出消息,在本地注册中心登记响应客户的需求 公众未来登记册(Msg m){ FutureMsg f=new MsgFuture();//未来句柄w.对空Msg对象的引用[=response] TxID uniqueID=协调_服务.建议;//事务ID 本地注册。添加(uniqueID,f); 返回f; } //由协调服务部呼叫,保证msg交付的全球订单 公共同步无效交付(TxID,Msg m){ …处理消息对象[请求] …如果本地注册表包含(id),“编译”响应 (当设置了某个消息标志时,使用FutureMsg f,f.get()-f.isDone()中的消息对象) ___现在: …通知正在等待的“工作者”线程检查其“未来”对象是否为一个() } 私有类Worker实现了Runnable{ ... 公开募捐{ ... Future f=Server.this.register(请求);//通过套接字s获得 而(!f.isDone()) 等待(); response=f.get(); ... } } },java,multithreading,deadlock,wait,notify,Java,Multithreading,Deadlock,Wait,Notify,我正在实现一个复制服务[多个服务器、客户端与单个服务器实例通信、创建/更新/删除操作将通过一个协调服务进行分发,该服务保证消息传递的全局顺序] 一旦客户端与服务器实例建立了新连接,所有通信都通过专用的工作者实例进行传输[该实例在本地处理读取请求,并使用服务器广播C/U/D操作。此.register(…)] register本身基本上记录未来本地处理/回复的请求,并将Msg对象转发给协调服务 服务通过deliver,…重新交付Msg对象,并在处理封装的任务后,应通知最初收到客户端请求的工作者实例移
工作者
实例进行传输[该实例在本地处理读取请求,并使用服务器广播C/U/D操作。此.register(…)
]
register
本身基本上记录未来本地处理/回复的请求,并将Msg
对象转发给协调服务
服务通过deliver
,…重新交付Msg
对象,并在处理封装的任务后,应通知最初收到客户端请求的工作者
实例移交相应的响应
由于某些原因,我的设计似乎被打破了…-w/osynchronized(this)
[在Worker\run()
]中,wait()
不会等待;使用synchronized(this)
,Server#deliver(…)
中的notifyAll()
将不会释放“阻塞的”工作者
实例上的锁
长话短说:事实证明,我需要你的帮助。。。或者(a):理解
wait/notify/notifyAll
的基本知识,或者(b):改进我的设计……或者(c):(a)和(b)。调用wait/notify
的线程需要锁定调用这些方法的对象,否则会出现异常。在一般形式中,假设一个任意对象:
// multiple server instances (replicas), coordinated using MsgCoordinationService
public class Server {
ConcurrentHashMap<TxID,Future<Msg>> local_registry = new ...
MsgCoordinationService coordination_service = new ..
...
// Socket instance to communicate with a client...
public void accept(Socket s) {
new Thread(new Worker(s)).start();
}
// propose msg to coordination service, register demand to respond to client in local registry
public Future<Msg> register(Msg m) {
FutureMsg f = new MsgFuture(); // Future handle w. reference to an empty Msg object [= response]
TxID uniqueID = coordination_service.propose(s); // transaction ID
local_registry.add(uniqueID, f);
return f;
}
// called by coordination service, guaranteeing a global order on msg deliveries
public synchronized void deliver(TxID id, Msg m) {
... process Msg object [request]
... if local_registry.contains(id), 'compile' response
(using the Msg object from FutureMsg f, f.get() - f.isDone() when a certain Msg flag has been set)
___ now:
... notify waiting 'Worker' threads to check whether their 'Future' object isDone()
}
private class Worker implements Runnable {
...
public void run() {
...
Future<Msg> f = Server.this.register(request); // obtained through Socket s
while(!f.isDone())
wait();
response = f.get();
...
}
}
}
notify
没有释放您的wait
的原因是您在调用notify
的对象之外的另一个对象中执行this.wait()
,因此它们没有配对。两个调用都需要使用相同的实例。您在Worker
的实例中执行this.wait()
,在Server
的实例中执行this.notifyAll()
,因此此
不引用同一对象
您应该创建一个跨类和线程可见的同步对象,并在该对象上进行同步
final Object obj = new Object();
...
synchronized(obj) {
while(/* condition */) {
obj.wait();
}
}