我有一个多线程服务器,请求即将到达服务器。 我们有两种类型的客户端。
一个是客户 其他是管理员
客户可以发送请求 客户可以取消请求 管理员可以接受请求
有两种不同的功能
一个是取消请求功能,即方法A. 另一种是接受请求函数,即方法B
客户要求将其标记为待处理。 现在管理员回复接受,同时客户取消
所以管理员认为他接受了这个请求 并且客户认为他取消了请求。
所以无论如何都要同步取消和接受方法。
//Cancel Request
public void A() {
int currentrequeststate = app.sharedData().getMap("users").get(user_id); //let say this is read as pending
if (currentrequeststate == RequestState.PENDING) {
currentrequeststate = RequestState.CANCEL;
app.sharedData().getMap("users").put(user_id, currentrequeststate);
//cancel it and sending cancel message
}
}
//Accept Request
public void B() {
int currentrequeststate = app.sharedData().getMap("users").get(user_id); //there is a chance this also read as pending
if (currentrequeststate == RequestState.CANCEL) {
//sending no trip to accept might be canceled
} else {
currentrequeststate = RequestState.ACCEPTED;
app.sharedData().getMap("users").put(user_id, currentrequeststate);
//Accept it and sending accept message
}
}
因为会有多个线程,并且这两个方法可以由不同的线程同时运行。 所以两种方法都有可能将当前currentrequeststate读取为pending 第一个方法A将取消请求 第二个方法B将接受请求
答案 0 :(得分:0)
我并不完全熟悉你所遇到的确切问题 解决但我会尝试下面的这些方面。
我会使用str
类型的数组String[1]
作为状态,而不仅仅是String
s;这样我就不会改变我同步的引用str
(我改变的是String
指向的str[0]
对象。
这也允许我通过不同的线程同时执行两个方法A
,如果它们位于不同user_id
的上下文中。我的同步仅在str
,即每user_id
。如果他们要求不同的A
,我不会阻止user_id
上的线程。实际上我认为user_id
应该是这两种方法的参数。
注意我如何比较字符串(使用等号,而不是==)
我认为RequestState
中的PENDING,ACCEPTED,CANCELED等常量是字符串。如果这个假设不正确,只需按照相同的逻辑稍微修改代码。
// Cancel Request
public void A() {
String[] str = app.sharedData().getMap("users").get(user_id);
synchronized(str){
String currentrequeststate = str[0];
if (RequestState.PENDING.equals(currentrequeststate) {
str[0] = RequestState.CANCELLED;
// cancel it and sending cancel message
}else if (RequestState.ACCEPTED.equals(currentrequeststate)){
// throw exception here (or take whatever action appropriate)
// as this request was already accepted by the admin;
// so it is too late for the user to cancel it
}
}
}
// Accept Request
public void B() {
String[] str = app.sharedData().getMap("users").get(user_id);
synchronized(str){
String currentrequeststate = str[0];
if (RequestState.CANCELLED.equals(currentrequeststate)) {
// Already cancelled, admin cannot accept it now as it's too late;
// so take whatever action is appropriate in this case
} else {
str[0] = RequestState.ACCEPTED;
// OK, accept it and sending accept message
}
}
}