草庐IT

关于C#:尝试使用pthread实现竞态条件

codeneng 2023-03-28 原文

Trying to implement race condition using pthread

我正在尝试设置比赛条件,以了解它是如何发生的。我写了下面的代码。这编译没有任何问题,但是当我运行它时,它不会在每次运行时打印计数。如果运行两次或三次,则打印计数。我的理解是否正确,在这段代码中,没有必要实际发生竞争条件。
(如果这是正确的,那么我不确定这是如何退出的,因为没有边界条件!)。如果我的理解不正确或代码,有人可以给我一些想法吗?

谢谢。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>

void *banking(void *);

int main(){
   int accounts[2]={0,0};
   pthread_t tid1,tid2;

     if(pthread_create(&tid1,NULL,banking,(void *)accounts))
     {
         perror("pthread_create");
          return 1;
     }


     if(pthread_create(&tid2,NULL,banking,(void *)accounts))
     {
          perror("pthread_create");
           return 1;
     }
     pthread_join(tid1, NULL);
     pthread_join(tid2, NULL);//program now goes into infinite loop.
    return 0;
    }

   void *banking(void * accounts){
        int *ptr=accounts;
        int count=0;
         do{
           int temp1=ptr[0];
           int temp2=ptr[1];
           int amount=rand();
             ptr[0]=temp1-amount;
             ptr[1]=temp2+amount;
              //printf("%d \
 %d\
",ptr[0],ptr[1]);

           count++;
            }while((ptr[0]+ptr[1])==0);
         printf("%d\
"
,count);
            //return NULL;
           exit(0);
           }

我试图实现 pthread_exit(NULL) 以实现线程在 do-while 循环结束后退出的逻辑,但根据我的理解,其他正在运行的线程不会以这种方式停止,因为程序会这样运行进入无限循环。我意识到任何线程的 exit() 都会终止进程并合并 exit(0) 。该代码适用于某些值,但随机生成两个不同的 \\'count\\' 值。这在 10-12 次尝试中发生一次。请建议是否建议在线程函数中使用 exit 以及在什么情况下我会有两个差异计数值。

  • 您在第二次调用 pthread_create 时遇到了复制和粘贴错误 - 您可能希望将 tid2 作为第一个参数。请注意,如果您使用 gcc -Wall 进行编译,您将收到关于此的编译器警告并节省一些调试时间。


1> 首先纠正"Paul R"提出的错误。然后

2>
您需要使用 pthread_join 函数来成功完成两个线程..

在这里创建两个线程后,主进程可能会结束,所以那时两个线程也都结束了,所以在 main() 中为两个线程使用 othread_join

将此代码添加到 main()

的末尾

1
2
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);

如果您仍然没有了解比赛条件的基础,请阅读以下部分。我从一本参考书中复制的

假设您的程序有一系列排队的作业,由几个
并发线程。作业队列由结构作业的链表表示
对象。

每个线程完成一个操作后,它会检查队列以查看是否有额外的
有工作。如果job_queue不为null,则线程移除链表的头部
并将 job_queue 设置为列表中的下一个作业。
处理队列中作业的线程函数可能类似于代码清单 4.10。
清单 4.10 (job-queue1.c) 处理队列中的作业的线程函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <malloc.h>
struct job {
/* Link field for linked list.
struct job* next;
*/

/* Other fields describing work to be done... */
};
/* A linked list of pending jobs.
struct job* job_queue;
*/

/* Process queued jobs until the queue is empty.
void* thread_function (void* arg)
{
while (job_queue != NULL) {
/* Get the next available job. */

struct job* next_job = job_queue;
/* Remove this job from the list. */
job_queue = job_queue->next;
/* Carry out the work. */
process_job (next_job);
/* Clean up. */
free (next_job);
}
return NULL;
}
*/
4.4
Synchronization and Critical Sections

现在假设两个线程恰好同时完成一项工作,但只
一个作业留在队列中。第一个线程检查 job_queue 是否为空;寻找-
知道它不是,线程进入循环并将指向作业对象的指针存储在
下一个工作。此时,Linux恰好中断了第一个线程并调度了
第二个。第二个线程还检查 job_queue 并发现它非空,也分配
指向下一个作业的相同作业指针。不幸的巧合,我们现在有两个
执行相同作业的线程。

更糟糕的是,一个线程会从队列中取消作业对象的链接,
留下job_queue包含null。当其他线程评估job_queue->next时,
将导致分段错误。

这是一个竞争条件的例子。在一个€?luckya€?情况下,这种特殊的
两个线程的调度可能永远不会发生,并且竞态条件可能永远不会发生
展示自己。只有在不同的情况下,也许是在重载上运行时
加载系统(或在重要客户的新多处理器服务器上!)可能
错误展示自己。

要消除竞争条件,您需要一种使操作原子化的方法。一个原子
操作是不可分割和不间断的;一旦操作开始,就不会
暂停或中断,直到完成,并且不会发生其他操作意味着-
尽管。在此特定示例中,您要检查 job_queue;如果它不是空的,
删除第一个作业,全部作为单个原子操作。

  • 嗨先生...我需要等待线程完成吗?因为我希望我的程序在竞争条件发生时立即退出。等待线程完成会有帮助吗?
  • 我认为在比赛条件 main 将终止之前.. 使用 sleep 或 thread_join 来查看它的效果
  • 添加了等待条件,程序输出计数器值,然后进入无限循环。即使我添加 pthread_exit,也会发生同样的事情。
  • 然后改变一些逻辑......!我希望你能做到这一点..!牢记线程的基本理解

有关关于C#:尝试使用pthread实现竞态条件的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  10. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

随机推荐