Java 使用有界缓冲区(生产者/消费者)能避免同步方法/死锁带来的痛苦吗?
我正在编写一个简单的银行模拟器,用户可以使用套接字从不同的位置同时登录。在银行服务器中,我保留一个有边界的缓冲区来存储每个传入的请求,例如:转账、获取帐户余额等,并且在服务器端有一个后台线程(缓冲区读取器)在FCFS的基础上从这个请求队列中取出每个请求(假设它在操作系统中作为线程调度器工作) 我使用了buffer的put()和get()方法来进行条件同步 例:Java 使用有界缓冲区(生产者/消费者)能避免同步方法/死锁带来的痛苦吗?,java,concurrency,synchronization,buffer,deadlock,Java,Concurrency,Synchronization,Buffer,Deadlock,我正在编写一个简单的银行模拟器,用户可以使用套接字从不同的位置同时登录。在银行服务器中,我保留一个有边界的缓冲区来存储每个传入的请求,例如:转账、获取帐户余额等,并且在服务器端有一个后台线程(缓冲区读取器)在FCFS的基础上从这个请求队列中取出每个请求(假设它在操作系统中作为线程调度器工作) 我使用了buffer的put()和get()方法来进行条件同步 例: // put method while(total_buffer_size == current_total_requests) {
// put method
while(total_buffer_size == current_total_requests) {
System.out.println("Buffer is full");
wait();
}
所以我的问题是,我们是否必须同步方法,如获取余额或转移资金,以避免数据损坏?我认为这是不必要的,因为缓冲区读取器会逐个执行每个请求和相关操作我是否通过此操作避免了任何死锁情况?你怎么认为?谢谢
编辑2:
public synchronized boolean put(Messenger msg, Thread t, Socket s) throws InterruptedException {
while(total_buffer_size == current_total_requests) {
System.out.println("Buffer is full");
wait();
}
current_total_requests++;
requests[cur_req_in] = new Request(msg, s); // insert into Queue
cur_req_in = (cur_req_in + 1) % total_buffer_size ;
notifyAll();
return true;
}
// take each incoming message in queue. FIFO rule followed
public synchronized Request get() throws InterruptedException {
while(current_total_requests==0) wait();
Request out = requests[cur_req_out];
requests[cur_req_out] = null;
cur_req_out = (cur_req_out + 1) % total_buffer_size ;
current_total_requests--;
notifyAll(); //wake all waiting threads to continue put()
return out;
}
如果只有一个使用者(即,一个线程使用来自“缓冲区”的请求),则不需要对与银行帐户相关的方法使用任何同步。但是,我不认为您当前的“有界缓冲区”实现是有效的。更具体地说:
while(total_buffer_size == current_total_requests) {
System.out.println("Buffer is full");
wait();
}
绝对不能保证有多少线程将通过while循环,在current\u total\u requests
增加之前执行上下文切换,队列中的请求超过允许的缓冲区大小。除非您的put
方法是同步的,否则这种方法将非常不可靠,并且容易出现竞争条件
如果您想要一个有界缓冲区,那么只需使用Java已经存在的一个“有界缓冲区”,或者更具体地说,即。BlockingQueue
阻塞put(…)
:
将指定的元素插入此队列,如有必要,等待空间变为可用
如果队列中没有数据,它还会阻塞
take()
。我不知道您是否可以使用并发库中的一项,但如果不能,则必须修复BoundedBuffer
,您不需要同步,因为您一次只执行一个操作。但是这会严重影响整体性能,因为如果您收到1000个请求,并且处理每个请求需要4毫秒,那么队列中的最后一个人必须等待将近4秒钟才能从服务器获得响应。好久不见了+1快速回复。这是一个学术项目,其中性能没有太多的考虑。我需要证明不会有任何僵局。感谢[引用]如果只有一个使用者(即一个线程使用“缓冲区”中的请求),那么您不需要对与银行帐户相关的方法使用任何同步。[/QUOTE]只有一个缓冲区读取器线程将从缓冲区中拉出请求,执行相关操作并确认发送请求的每个线程。必须使用我自己的有界缓冲区。@coder,kk,我刚看到你的编辑,它看起来很好,因为你同步了put
/get
。你可以忽略我最初对比赛条件的担忧。您应该检查“角落”情况,例如如果用户创建大小为0的有界缓冲区,并且您尝试放置
/获取
?1号怎么样?(我还没有研究过你的逻辑,看看会发生什么,但你可能想考虑一下)