问题
The definition of a race condition: A race condition or race hazard is a flaw in a system or process whereby the output or result of the process is unexpectedly and critically dependent on the sequence or timing of other events.
Consider the following pseudocode:
Global variable i initialized to 6;
Thread 1:
acquire(lock l)
increment global variable i, i.e. i++;
Thread 2:
acquire(lock l)
double the value of global var i, i.e.: i*=2;
If T1 acquires the lock l first and T2 second the value of i will be 14. On the other hand, if T2 acquires the lock l first and T1 second the value of i will be 13.
So, is this a race condition or not ?
UPDATE: after a number of comments and answers, the opinions are still divergent. My opinion is in the "YES, this is a race condition" category. Actually I gave this example as a race condition situation, on a different question. At the same time, I also read some interesting comments in the "NO, this isn't a race condition" category. I think I will settle and conclude that this is or isn't a race condition depending on the perspective/level from which one looks at the problem. However, I'm still waiting for interesting answers/comments.
回答1:
I think whether the example algorithm has a race condition depends on the what the algorithm is expected to do.
There is no data race on the modification of i
- those accesses are serialized and occur atomically with respect to each other.
However, if it's important to the correctness of the algorithm that the increment occur before the multiplication (or vice versa), then there is a race and other means would have to be used to synchronize the execution of the algorithm. If the algorithm is supposed to be a complicated way to calculate i * 2 + 1
(as ridiculous as it might be to perform the calculation using threads), then there's a race condition.
Consider the following program snippet:
int data;
pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mux = PTHREAD_MUTEX_INITIALIZER;
void* wait_for_data(void*)
{
pthread_mutex_lock( &mux);
pthread_cond_wait( &condvar, &mux);
puts("got the data: %d\n", data);
pthread_mutex_unlock( &mux);
return 0;
}
void* set_data(void*)
{
pthread_mutex_lock( &mux);
data = 42;
pthread_cond_signal( &condvar);
pthread_mutex_unlock( &mux);
return 0;
}
Both threads are essentially completely mutually exclusive - there is no data race. However, if set_data()
signals the condition variable before wait_for_data()
gets around to waiting on it, wait_for_data()
will never complete. I think most people would call that a race condition due to improper use of the condition variable.
回答2:
No it's not. Because it locks before reading and writing to i. So the reads and writes in your example are always consistent. Of course you should unlock after each operation, but I guess you just forgot to add that in your pseudo-code.
回答3:
No, this is one of the expected sequences of execution. A race would be not protecting the counter with some sort of a lock, thus allowing for load-modify-store cycles to run concurrently.
Edit 0:
@Gheorghe, think about an example of a joint bank account and two people taking their money out of it at difference bank offices at the same time. A clerk at each location would need to check account balance, give out cash, and write down new balance. If this is not "atomic" with regard to the balance, i.e. the account is not "locked" during this operation, they might end up getting more money between two of them then they had in the bank. Banks don't like that.
But if the account is locked while being manipulated, does the output depend on the timing? Yes, absolutely - total sum doesn't change, but the split between two of them can be different.
What matters is the consistency of the protected value - no matter in what sequence and how many times these two guys take money from the back, they don't get more then they originally had.
回答4:
Note: I give an answer from a Java perspective as the question originated from a previous discussion about the Java Memory Model.
There seems to be a lot of confusion around the definition of "race condition", which is why you are getting different answers.
If you mean "data race", there is only one valid definition in the context of Java, and it is given by the Java Language Specification 17.4.5:
When a program contains two conflicting accesses (§17.4.1) that are not ordered by a happens-before relationship, it is said to contain a data race.
Conflicting accesses is defined in 17.4.1:
Two accesses to (reads of or writes to) the same variable are said to be conflicting if at least one of the accesses is a write.
In your case, your code contains a happens-before relationship as defined by 17.4.5:
An unlock on a monitor happens-before every subsequent lock on that monitor.
So there is no data race in your code in a Java context - anyone saying otherwise is using a non-Java definition.
Others have commented about a "general race" in the sense that any of the 2 codes could run first, but that's an algorithm question: either your code is parallelizable and it should not matter, or it is not and you should run it sequentially. But that's a bug, not a data race.
回答5:
yes. by definition it is. Also you will have a problem with variable volatility. In this case there is no guarantee which thread loads the variable from memory to which register and then saves it to memory. So it might be that in some cases,one thread will get a stale value. In many languages you will have to somehow make sure that you will always fetch a clean copy. (in java volatile)
http://www.freebsd.org/doc/en/books/developers-handbook/secure-race-conditions.html
I think that is a good definition also.
Reading: http://dl.acm.org/citation.cfm?id=130623
"Two different notions have been implicitly considered: one pertaining to programs intended to be deterministic (which we call general races) and the other to nondeterministic programs containing critical sections (which we call data races)."
so I would say that it is a "general race" if you assumed that program to always produce the same result. If not, you just have very weird design.
来源:https://stackoverflow.com/questions/12007205/is-this-a-race-condition