这段代码有竞争条件吗?
Does this code have a race condition?
我只需要用 java 个线程做一个竞争条件的例子,我写了这段代码,但我不确定它是否有竞争条件。
谁能告诉我下面的代码是否存在竞争条件,我该如何改进或简化它?
(抱歉英语不好)
public class RaceCondition extends Thread{
static int count=0; //the variable where the race condition need to happen
static int contador1 = 0; //variables to count
static int contador2 = 0;
static Thread t1 = new Thread(new Runnable() {
public void run(){
while(contador1!=20){
count ++;
System.out.print(count + " ");
contador1++;
}
}
});
static Thread t2 = new Thread(new Runnable() {
public void run(){
while(contador2!=20){
int k = 5;
count += 5*k;
System.out.print(count + " ");
contador2 ++;
}
}
});
public static void main(String[] args) {
t1.start();
System.out.println(" ");
t2.start();
}
}
您没有任何比赛条件。线程仅分别访问变量 contador1
和 contador2
。没有变量被两个线程修改或读取。
t2
甚至有它自己使用的本地 k
,而不是您标记的 k
。
count
声明在哪里?
为了有竞争条件,你需要有线程read/write共享内存部分(例如global/static变量)。在这里,您的线程不交互,因此没有竞争条件。此外,您在线程 2 代码中重新声明 k
,因此您的全局 k
永远不会被使用。
试试这个:
public class RaceCondition extends Thread{
static int k = 0; //the variable where the race condition need to happen
public void run(){
while( k != 20 ){
k++;
try{
Thread.sleep( 1 );
}catch( InterruptedException e ){
}
System.out.print( k + " " );
}
}
public static void main( String[] args ){
RaceCondition t1 = new RaceCondition();
RaceCondition t2 = new RaceCondition();
t1.start();
t2.start();
}
}
"A race condition occurs when two or more threads can access shared data and they try to change it at the same time. Because the thread scheduling algorithm can swap between threads at any time, you don't know the order in which the threads will attempt to access the shared data. Therefore, the result of the change in data is dependent on the thread scheduling algorithm, i.e. both threads are "与“access/change 数据赛跑。”
来源 = What is a race condition?
请注意这部分 "the result of the change in data is dependent on the thread scheduling algorithm" 以及如何在您的代码中操作变量计数。
没有。当两个或多个线程访问导致结果出现问题的同一个变量时,就会出现竞争条件。例如,
static int a = 2;
static int b = 0;
static Thread t1 = new Thread(new Runnable() {
public void run(){
if(a == 2) {
b = 5 * a;
System.out.println(a);
}
}
});
static Thread t2 = new Thread(new Runnable() {
public void run(){
a = 5;
}
});
这里,考虑Thread1刚执行完if(a == 2)
,Thread2改变了a = 5
的值。因此,我们将得到 25
.
而不是预期值 10
这是代码:
package RaceCondition;
public class RaceCondition extends Thread {
static int count = 0;
static int contador1 = 0;
static int contador2 = 0;
static Thread t1 = new Thread(new Runnable() {
public void run() {
while (contador1 != 20) {
count++;
System.out.print(count + " ");
contador1++;
}
System.out.println("fine t1");
}
});
static Thread t2 = new Thread(new Runnable() {
public void run() {
while (contador2 != 20) {
int k = 5;
count += 5;
System.out.print(count + " ");
contador2++;
}
System.out.println("fine t2");
}
});
public static void main(String[] args) {
t1.start();
System.out.println(" ");
t2.start();
}
}
您确实存在竞争条件。 ++
或 +=
操作都没有作为原子操作在 Java 中实现,这两个线程在尝试读取和更新计数字段时可能会相互干扰。
同时也不能保证对共享变量的更新在线程之间可见,因此一个线程甚至可能看不到另一个线程的更新值。
您可以通过将计数静态变量设为 AtomicInteger. Use getAndIncrement instead of ++
, and getAndAdd 而不是 +=
.
来解决这两个问题
为什么 ++
会这样工作,请参阅 Why ++ is not implemented as an atomic operation in Java。
我只需要用 java 个线程做一个竞争条件的例子,我写了这段代码,但我不确定它是否有竞争条件。
谁能告诉我下面的代码是否存在竞争条件,我该如何改进或简化它?
(抱歉英语不好)
public class RaceCondition extends Thread{
static int count=0; //the variable where the race condition need to happen
static int contador1 = 0; //variables to count
static int contador2 = 0;
static Thread t1 = new Thread(new Runnable() {
public void run(){
while(contador1!=20){
count ++;
System.out.print(count + " ");
contador1++;
}
}
});
static Thread t2 = new Thread(new Runnable() {
public void run(){
while(contador2!=20){
int k = 5;
count += 5*k;
System.out.print(count + " ");
contador2 ++;
}
}
});
public static void main(String[] args) {
t1.start();
System.out.println(" ");
t2.start();
}
}
您没有任何比赛条件。线程仅分别访问变量 contador1
和 contador2
。没有变量被两个线程修改或读取。
t2
甚至有它自己使用的本地 k
,而不是您标记的 k
。
count
声明在哪里?
为了有竞争条件,你需要有线程read/write共享内存部分(例如global/static变量)。在这里,您的线程不交互,因此没有竞争条件。此外,您在线程 2 代码中重新声明 k
,因此您的全局 k
永远不会被使用。
试试这个:
public class RaceCondition extends Thread{
static int k = 0; //the variable where the race condition need to happen
public void run(){
while( k != 20 ){
k++;
try{
Thread.sleep( 1 );
}catch( InterruptedException e ){
}
System.out.print( k + " " );
}
}
public static void main( String[] args ){
RaceCondition t1 = new RaceCondition();
RaceCondition t2 = new RaceCondition();
t1.start();
t2.start();
}
}
"A race condition occurs when two or more threads can access shared data and they try to change it at the same time. Because the thread scheduling algorithm can swap between threads at any time, you don't know the order in which the threads will attempt to access the shared data. Therefore, the result of the change in data is dependent on the thread scheduling algorithm, i.e. both threads are "与“access/change 数据赛跑。” 来源 = What is a race condition?
请注意这部分 "the result of the change in data is dependent on the thread scheduling algorithm" 以及如何在您的代码中操作变量计数。
没有。当两个或多个线程访问导致结果出现问题的同一个变量时,就会出现竞争条件。例如,
static int a = 2;
static int b = 0;
static Thread t1 = new Thread(new Runnable() {
public void run(){
if(a == 2) {
b = 5 * a;
System.out.println(a);
}
}
});
static Thread t2 = new Thread(new Runnable() {
public void run(){
a = 5;
}
});
这里,考虑Thread1刚执行完if(a == 2)
,Thread2改变了a = 5
的值。因此,我们将得到 25
.
这是代码:
package RaceCondition;
public class RaceCondition extends Thread {
static int count = 0;
static int contador1 = 0;
static int contador2 = 0;
static Thread t1 = new Thread(new Runnable() {
public void run() {
while (contador1 != 20) {
count++;
System.out.print(count + " ");
contador1++;
}
System.out.println("fine t1");
}
});
static Thread t2 = new Thread(new Runnable() {
public void run() {
while (contador2 != 20) {
int k = 5;
count += 5;
System.out.print(count + " ");
contador2++;
}
System.out.println("fine t2");
}
});
public static void main(String[] args) {
t1.start();
System.out.println(" ");
t2.start();
}
}
您确实存在竞争条件。 ++
或 +=
操作都没有作为原子操作在 Java 中实现,这两个线程在尝试读取和更新计数字段时可能会相互干扰。
同时也不能保证对共享变量的更新在线程之间可见,因此一个线程甚至可能看不到另一个线程的更新值。
您可以通过将计数静态变量设为 AtomicInteger. Use getAndIncrement instead of ++
, and getAndAdd 而不是 +=
.
为什么 ++
会这样工作,请参阅 Why ++ is not implemented as an atomic operation in Java。