为什么在此示例中,线程连接的行为会有所不同? - c#

更新问题以使其更通用:

我有以下代码。交换线程[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本身是线程安全的吗? - java

Java 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调用-第二个请求在应用程序中的另一个线程中处理,并且由于应用程序的大部分都是特定于会话…