jil*_*lro 22 concurrency multithreading race-condition
你可以在这里找到关于什么是竞争条件的非常好的解释.
我最近看到很多人对竞争条件和线程做出令人困惑的陈述.
我了解到竞争条件只能在线程之间发生.但我看到的代码看起来像竞争条件,在事件和基于异步的语言中,即使程序是单线程,如在Node.js,GTK +等.
我们可以在一个线程程序中遇到竞争条件吗?
jil*_*lro 30
所有示例都是一种非常接近Javascript的虚构语言.
短:
竞争条件只能在两个或多个线程之间发生.我们不能在单个线程进程中具有竞争条件(例如,在单个线程中,非I/O执行程序).
但在许多情况下,单个线程程序可以:
给出类似于竞争条件的情况,例如在具有事件循环的基于事件的程序中,但不是真实的竞争条件
触发其他线程之间或与其他线程的竞争条件,例如:
只有当两个或多个线程尝试访问共享资源而不知道其他线程的未知指令同时修改共享资源时,才会发生竞争条件.这给出了未确定的结果.(这非常重要.)
单个线程进程只不过是一系列已知指令,因此即使指令的执行顺序在代码中不易读取,也会产生确定的结果.
许多编程语言通过事件或信号实现异步编程功能,由主循环或事件循环处理,检查事件队列并触发侦听器.这方面的例子是Javascript,libuevent,reactPHP,GNOME GLib ......有时,我们可以找到似乎是竞争条件的情况,但事实并非如此.
调用事件循环的方式始终是已知的,因此即使指令的执行顺序不易读取(或者如果我们不知道库也无法读取),也会确定结果.
例:
setTimeout(
function() { console.log("EVENT LOOP CALLED"); },
1
); // We want to print EVENT LOOP CALLED after 1 milliseconds
var now = new Date();
while(new Date() - now < 10) //We do something during 10 milliseconds
console.log("EVENT LOOP NOT CALLED");
Run Code Online (Sandbox Code Playgroud)
在Javascript输出中总是(你可以在node.js中测试):
EVENT LOOP NOT CALLED
EVENT LOOP CALLED
Run Code Online (Sandbox Code Playgroud)
因为,当堆栈为空(所有函数都已返回)时,将调用事件循环.
请注意,这只是一个示例,并且在以不同方式实现事件的语言中,结果可能不同,但仍然由实现决定.
如果其他进程正在请求我们的进程,我们的程序不以原子方式处理请求,并且我们的进程在请求之间共享一些资源,则客户端之间可能存在竞争条件.
例:
var step;
on('requestOpen')(
function() {
step = 0;
}
);
on('requestData')(
function() {
step = step + 1;
}
);
on('requestEnd')(
function() {
step = step +1; //step should be 2 after that
sendResponse(step);
}
);
Run Code Online (Sandbox Code Playgroud)
在这里,我们有一个经典的竞赛条件设置.如果请求在另一个结束之前打开,step则将重置为0.如果requestData在requestEnd两个并发请求之前触发了两个事件,则步骤将达到3. 但这是因为我们将事件序列视为未确定.我们期望程序的结果大部分时间未确定,输入未确定.
实际上,如果我们的程序是单线程,给定一系列事件,结果仍然总是被确定.竞争条件是客户之间.
有两种方法可以理解这件事:
return input;也会产生不确定的结果.注意 :
在我们的程序中,我们经常使用产生其他进程或线程的库,或者只使用其他进程执行I/O(并且I/O总是未确定).
示例:
databaseClient.sendRequest('add Me to the database');
databaseClient.sendRequest('remove Me from the database');
Run Code Online (Sandbox Code Playgroud)
这可以触发异步库中的竞争条件.如果sendRequest()在将请求发送到数据库之后但在请求真正执行之前返回,则会出现这种情况.我们立即发送另一个请求,我们无法知道在评估第二个请求之前是否会执行第一个请求,因为数据库在另一个线程上工作.程序和数据库进程之间存在竞争条件.
但是,如果数据库与程序在同一个线程上(在现实生活中并不经常发生),则在处理请求之前sendRequest将无法返回.(除非请求排队,但在这种情况下,结果仍然是确定的,因为我们确切地知道如何以及何时读取队列.)
简而言之,单线程程序并非免于竞争条件.但它们只能在外部程序的其他线程之间或之间发生.我们的计划结果可能未确定,因为我们的计划从其他计划收到的输入未确定.
| 归档时间: |
|
| 查看次数: |
5434 次 |
| 最近记录: |