首页 \ 问答 \ 为什么代码在线程之间突变共享变量显然不会受到竞争条件的影响?(Why does code mutating a shared variable across threads apparently NOT suffer from a race condition?)

为什么代码在线程之间突变共享变量显然不会受到竞争条件的影响?(Why does code mutating a shared variable across threads apparently NOT suffer from a race condition?)

我正在使用Cygwin GCC并运行此代码:

#include <iostream>
#include <thread>
#include <vector>
using namespace std;

unsigned u = 0;

void foo()
{
    u++;
}

int main()
{
    vector<thread> threads;
    for(int i = 0; i < 1000; i++) {
        threads.push_back (thread (foo));
    }
    for (auto& t : threads) t.join();

    cout << u << endl;
    return 0;
}

用行编译: g++ -Wall -fexceptions -g -std=c++14 -c main.cpp -o main.o

它打印1000,这是正确的。 但是,由于线程覆盖了先前递增的值,我预计会导致较少的数字。 为什么这个代码不会相互访问?

我的测试机有4个核心,我没有限制我所知道的程序。

当用更复杂的东西替换共享foo的内容时,问题仍然存在,例如

if (u % 3 == 0) {
    u += 4;
} else {
    u -= 1;
}

I'm using Cygwin GCC and run this code:

#include <iostream>
#include <thread>
#include <vector>
using namespace std;

unsigned u = 0;

void foo()
{
    u++;
}

int main()
{
    vector<thread> threads;
    for(int i = 0; i < 1000; i++) {
        threads.push_back (thread (foo));
    }
    for (auto& t : threads) t.join();

    cout << u << endl;
    return 0;
}

Compiled with the line: g++ -Wall -fexceptions -g -std=c++14 -c main.cpp -o main.o.

It prints 1000, which is correct. However, I expected a lesser number due to threads overwriting a previously incremented value. Why does this code not suffer from mutual access?

My test machine has 4 cores, and I put no restrictions on the program that I know of.

The problem persists when replacing the content of the shared foo with something more complex, e.g.

if (u % 3 == 0) {
    u += 4;
} else {
    u -= 1;
}

原文:https://stackoverflow.com/questions/41816495
更新时间:2022-05-03 18:05

最满意答案

默认的HttpClient.Timeout值为100秒(00:01:40)。 如果你在catch块中做一个时间戳记,你会注意到这个任务在那个时候开始被取消了。 显然,您每秒可以执行的HTTP请求数量有限,其他人则排队等候。 排队的请求在超时时被取消。 在所有600k的任务中,我个人成功只有2500人,其他人被取消了。

我也发现不太可能,你将能够运行整个60万个任务。 许多网络驱动程序只允许很长时间的大量请求,并在一段时间后将该数量减少到非常低的值。 我的网卡允许我在36秒内只发送921个请求,并将该速度降低到每秒只有一个请求。 以这个速度,完成所有的任务将需要一个星期。

如果您能够绕过此限制,请确保为64位平台构建代码,因为该应用程序非常渴望内存。


The default HttpClient.Timeout value is 100 seconds (00:01:40). If you do a timestamp in your catch block you will notice that tasks begin to get canceled at exactly that time. Apparently there is a limited number of HTTP requests you can do per second, others get queued. Queued requests get canceled on timeout. Out of all 600k of tasks I personally got only 2500 successful, others got canceled.

I also find it unlikely, that you will be able to run the whole 600000 of tasks. Many network drivers let through high number of requests only for a small time, and reduce that number to a very low value after some time. My network card allowed me to send only 921 requests within 36 seconds and dropped that speed to only one request per second. At that speed it will take a week to complete all the tasks.

If you are able to bypass that limitation, make sure you build the code for 64-bit platform as the app is very hungry for memory.

相关问答

更多
  • 我们有一个相当可观的用户群,通过移动连接购买东西,只显示提醒 code != SKErrorPaymentCancelled && code != SKErrorPaymentNotAllowed 显然,这是你能做的最好的。 我也看到了你提到的取消上的奇怪行为,据我所知,这是一个框架错误。 We have a pretty substantial user base buying stuff over mobile connections and only show alerts for code != ...
  • 有两个可能的原因是TaskCanceledException将被抛出: 在任务完成之前,与取消令牌相关联的CancellationTokenSource上的Cancel() CancellationTokenSource 。 请求超时,即在您在HttpClient.Timeout指定的时间段内未完成。 我的猜测是这是一个超时。 (如果是明确的取消,你可能会想到这一点)。通过检查异常可以更加确定: try { var response = task.Result; } catch (TaskCance ...
  • 超时的默认值为100秒。 您可以使用Timeout属性将HTTPClient上的超时时间提高到3分钟(或更高)。 httpClient.Timeout = new TimeSpan(0,3,0); The default value for the timeout is 100 seconds. You can up the timeout on the HTTPClient to 3 minutes(or higher) using the Timeout property. httpClient. ...
  • 默认的HttpClient.Timeout值为100秒(00:01:40)。 如果你在catch块中做一个时间戳记,你会注意到这个任务在那个时候开始被取消了。 显然,您每秒可以执行的HTTP请求数量有限,其他人则排队等候。 排队的请求在超时时被取消。 在所有600k的任务中,我个人成功只有2500人,其他人被取消了。 我也发现不太可能,你将能够运行整个60万个任务。 许多网络驱动程序只允许很长时间的大量请求,并在一段时间后将该数量减少到非常低的值。 我的网卡允许我在36秒内只发送921个请求,并将该速度降低 ...
  • 感谢Ankit Vijay的回应,答案必须与您提及的时间一致,我的解决方案就是下一个 我正在使用jsreport embbedserver,并且像这样设置了时间 embeddedReportingServer.ReportingService.HttpClientTimeout = TimeSpan.FromMinutes(40); 用这行代码我停止接收这个错误: TaskCanceledException:任务在呈现jsreport时被取消 然后当我再次测试时,我用phanton过程得到了这个错误: 无 ...
  • 您的第一个任务实际上并未被取消 - 您正在观察已经请求取消,但是您正在让第一个任务正常完成...这意味着您的“仅取消”任务被取消。 如果您将代码更改为: while (token.IsCancellationRequested == false) { Console.Write("*"); Thread.Sleep(1000); } token.ThrowIfCancellationRequested(); ......然后它会按照你的预期行事。 Your first task isn't ...
  • 有不同的方法来模拟这个。 您可以使用中断边界消息接收事件,如果收到额外信息,则边界事件将取消用户任务。 另一种方法是使用中断事件子过程。 如果收到带有额外信息的消息,则触发事件子过程并取消该过程。 您还可以使用并行网关和终止结束事件。 但我会推荐上述方法之一。 There are different ways to model this. You could use an interrupting boundary message receive event and if the extra info wa ...
  • 您的解决方案不完善,因为在您调用isCancelled()和调用get()之间可能会发生取消,这很少会导致异常。 更好的方法是捕获CancellationException并处理它。 Your solution is imperfect since cancellation could occur between the time you call isCancelled() and the time you call get() which would, rarely, still result in t ...
  • 我不确定回答我自己的任务是否正常,所以我不会将其标记为答案,也许有人想出一个更好的解决方案:P 首先,这里是生产者代码: static async Task StartAsync() { using (var queue = new SendMessageQueue(10, new SendMessageService())) using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(4. ...
  • 经过6天不间断的挣扎,以及谷歌搜索不停的解决方案后,我很高兴地说我终于明白了。 转向我们,无论出于什么神秘的原因, uploadTask(with:from:completionHandler)的from:参数uploadTask(with:from:completionHandler)都不能为零。 尽管参数被标记为可选Data ,但它在缺失时会立即被取消。 这可能是Apple方面的一个错误,当我无法使其工作时我打开了一个错误,因此我将使用这些新信息更新我的错误报告。 话虽如此,我所要做的就是更新我的bui ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。