gpt4 book ai didi

java - 在线程之间共享资源,不同 java 版本中的不同行为

转载 作者:搜寻专家 更新时间:2023-11-01 02:13:14 24 4
gpt4 key购买 nike

这是我第一次遇到类似下面的事情。

  • 多个线程(实现 Runnable 的内部类)共享一个数据结构(上层类的实例变量)。

  • 工作:从 Eclipse 项目的 bin 文件夹中获取类,在 Unix 机器上运行。

  • 不工作:直接在 Unix 机器上编译 src 并使用那些类文件。代码编译并运行,没有错误/警告,但一个线程无法正确访问共享资源。

  • 问题:一个线程向上述公共(public) DS 添加元素。第二个线程执行以下操作...

      while(true){
    if(myArrayList.size() > 0){
    //do stuff
    }

  • Log 显示线程 1 中更新了大小。

  • 由于某些神秘原因,工作流没有进入 if() ...

如果我直接从 Eclipse 的 bin 文件夹中粘贴类文件,同样的代码可以完美运行。

如果我遗漏了任何明显的内容,我深表歉意。

代码:

ArrayList<CSRequest> newCSRequests = new ArrayList<CSRequest>();

//线程1

private class ListeningSocketThread implements Runnable {
ServerSocket listeningSocket;

public void run() {
try {
LogUtil.log("Initiating...");
init(); // creates socket
processIncomongMessages();
listeningSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

private void processIncomongMessages() throws IOException {
while (true) {
try {
processMessage(listeningSocket.accept());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

private void processMessage(Socket s) throws IOException, ClassNotFoundException {
// read message
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
Object message = ois.readObject();
LogUtil.log("adding...: before size: " + newCSRequests.size());
synchronized (newCSRequests) {
newCSRequests.add((CSRequest) message);
}
LogUtil.log("adding...: after size: " + newCSRequests.size()); // YES, THE SIZE IS UPDATED TO > 0
//closing....

}

........

//Thread 2
private class CSRequestResponder implements Runnable {

public void run() {
LogUtil.log("Initiating..."); // REACHES..
while (true) {
// LogUtil.log("inside while..."); // IF NOT COMMENTED, FLOODS THE CONSOLE WITH THIS MSG...
if (newCSRequests.size() > 0) { // DOES NOT PASS
LogUtil.log("inside if size > 0..."); // NEVER REACHES....
try {
handleNewCSRequests();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
....
}

更新

解决方案是在我检查线程 2 中的大小之前添加 synchronized(myArrayList)。

最佳答案

要在多线程环境中访问共享结构,您应该使用隐式或显式锁定来确保线程间的安全发布和访问。使用上面的代码,它应该是这样的:

while(true){
synchronized (myArrayList) {
if(myArrayList.size() > 0){
//do stuff
}
}
//sleep(...) // outside the lock!
}

注意:此模式看起来很像 producer-consumer并且使用队列更好地实现。 LinkedBlockingQueue是一个很好的选择,并提供内置的并发控制功能。这是在线程间安全发布数据的良好结构。使用并发数据结构可以让您摆脱同步块(synchronized block):

Queue queue = new LinkedBlockingQueue(...)
...
while(true){
Data data = queue.take(); // this will wait until there's data in the queue
doStuff(data);
}

关于java - 在线程之间共享资源,不同 java 版本中的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13082037/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com