更新问题以使其更通用:
我有以下代码。交换线程[i] .Join()的位置时,将得到不同的输出。
static void ThreadedWorker(int startIndex, int endIndex)
{
Console.WriteLine("Working from results[ " + startIndex +"] to results["+endIndex+"]");
}
static void Main(string[] args)
{
int threadCount = System.Environment.ProcessorCount;
int calculationCount = 500; //the number of array elements we'd be iterating over if we were doing our work
int threadDataChunkSize = calculationCount / threadCount;
if (threadDataChunkSize < 1) threadDataChunkSize = 1; //just in case we have loads of threads
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++)
{
threads[i] = new Thread(() => ThreadedWorker(threadDataChunkSize * i, threadDataChunkSize*(i+1)));
threads[i].Start();
//threads[i].Join(); //****Uncomment for correct behaviour****
}
for (int i = 0; i < threadCount; i++)
{
//threads[i].Join(); //****Uncomment for incorrect behaviour****
}
Console.WriteLine("breakhere");
}
当Join()
在第一个循环中创建顺序行为时,您将获得输出
Working from results[ 0] to results[125]
Working from results[ 125] to results[250]
Working from results[ 250] to results[375]
Working from results[ 375] to results[500]
当Join()
在第二个循环中创建并行行为时,您将得到不确定的输出,例如:
Working from results[ 375] to results[500]
Working from results[ 375] to results[500]
Working from results[ 500] to results[625]
Working from results[ 500] to results[625] (i is sometimes more than it should ever be!)
我的怀疑是lambda表达式以某种方式导致了问题。希望这种改写也可以证明这不是对计算的误解或其他滥用!
最初的问题不太通用,并使用startIndex和endIndex遍历了工作的字节数组。我将ThreadedWorker
描述为“不起作用”,因为它有时会更新结果数组,有时却不会。现在看来它已被调用,但是startindex和endindex被破坏了。
参考方案
您的解决方案是正确的,但是您误解了问题。
Lambda表达式是线程安全的。
但是,您所有的lambda表达式都共享相同的i
变量。
因此,如果其中一个线程恰好在循环前进到下一个迭代之后开始,它将获取新的i
值。
通过在循环内声明一个单独的变量,您将迫使每个lambda使用其自己的变量,该变量永远不会改变。
此代码不是线程安全的吗? - java我期望这段代码是线程安全的。我运行了几次,但是得到了不同的结果。但是,如果我取消注释sleep(1000)部分,则每次都会打印10000(至少从我的测试运行结果中得出)。那怎么了可能与thread.join()有关吗?public class Test implements Runnable{ private int x; public synchroniz…
哈希映射的线程安全实现 - java首先,我将描述我想要的东西,然后详细说明我正在考虑的可能性。我不知道哪个是最好的,所以我需要一些帮助。我有一个哈希映射,可以从Servlet读取和写入操作。现在,由于此Servlet在Tomcat上,因此我需要哈希映射来确保线程安全。基本上,当它被写入时,没有其他内容可以写入,也没有任何内容也可以读取。我看过ConcurrentHashMap,但是注意到它的…
DefaultThreadFactory本身是线程安全的吗? - javaJava Executor框架提供用于创建线程的DefaultThreadFactory。DefaultThreadFactory本身对于多个线程并发使用是否安全?还是我必须注意每个线程只有一个DefaultThreadFactory?我知道通常最好的做法是仅从一个“主”线程启动新线程,但让我们假设一个预先存在的代码库。如果答案中包含简短的解释,说明为什么您…
在Java中停止执行几秒钟的最佳方法是什么? - java我是Java新手。我试图编写一个程序来检查数据库状态(是否过载)。码:package com.test.service; import java.util.LinkedList; import java.util.List; public class PersonImpl { public PersonService personService; publi…
Wicket:如何在会话中同步请求 - java场景:在Tomcat服务器上运行的基于Apache Wicket的Web应用程序。用户在浏览器中打开URL,创建会话并在浏览器中显示简单的主页,用户单击按钮并调用AJAX调用。应用程序获取请求并做一些准备响应的工作。同时浏览器中的用户或JavaScript调用另一个AJAX调用-第二个请求在应用程序中的另一个线程中处理,并且由于应用程序的大部分都是特定于会话…