国内java有什么比赛_什么是比赛条件? - javail的个人空间 - OSCHINA - 中文开源技术交流社区...

在编写多线程应用程序时,遇到的最常见问题之一是竞争条件。

我对社区的问题是:

什么是比赛条件? 您如何检测到它们? 您如何处理它们? 最后,如何防止它们发生?

#1楼

当设备或系统试图同时执行两个或多个操作时,竞争状态是一种不希望出现的情况,但是由于设备或系统的性质,必须按照正确的顺序进行操作才能被执行。正确完成。

在计算机内存或存储中,如果几乎在同一时刻接收到读取和写入大量数据的命令,并且机器尝试覆盖部分或全部旧数据,而仍旧保留旧数据,则可能会发生竞争状态读。 结果可能是以下一种或多种:计算机崩溃,“非法操作”,程序的通知和关闭,读取旧数据时出错或写入新数据时出错。

#2楼

微软实际上已经发布了有关种族条件和僵局问题的非常详细的文章 。 其中最概括的摘要是标题段落:

当两个线程同时访问一个共享变量时,就会发生竞争状态。 第一个线程读取变量,第二个线程从变量读取相同的值。 然后,第一个线程和第二个线程对值执行操作,然后争先看哪个线程可以最后将值写入共享变量。 保留最后写入其值的线程的值,因为该线程正在覆盖前一个线程写入的值。

#3楼

请尝试以下基本示例,以更好地了解比赛条件:

public class ThreadRaceCondition {

/**

* @param args

* @throws InterruptedException

*/

public static void main(String[] args) throws InterruptedException {

Account myAccount = new Account(22222222);

// Expected deposit: 250

for (int i = 0; i < 50; i++) {

Transaction t = new Transaction(myAccount,

Transaction.TransactionType.DEPOSIT, 5.00);

t.start();

}

// Expected withdrawal: 50

for (int i = 0; i < 50; i++) {

Transaction t = new Transaction(myAccount,

Transaction.TransactionType.WITHDRAW, 1.00);

t.start();

}

// Temporary sleep to ensure all threads are completed. Don't use in

// realworld :-)

Thread.sleep(1000);

// Expected account balance is 200

System.out.println("Final Account Balance: "

+ myAccount.getAccountBalance());

}

}

class Transaction extends Thread {

public static enum TransactionType {

DEPOSIT(1), WITHDRAW(2);

private int value;

private TransactionType(int value) {

this.value = value;

}

public int getValue() {

return value;

}

};

private TransactionType transactionType;

private Account account;

private double amount;

/*

* If transactionType == 1, deposit else if transactionType == 2 withdraw

*/

public Transaction(Account account, TransactionType transactionType,

double amount) {

this.transactionType = transactionType;

this.account = account;

this.amount = amount;

}

public void run() {

switch (this.transactionType) {

case DEPOSIT:

deposit();

printBalance();

break;

case WITHDRAW:

withdraw();

printBalance();

break;

default:

System.out.println("NOT A VALID TRANSACTION");

}

;

}

public void deposit() {

this.account.deposit(this.amount);

}

public void withdraw() {

this.account.withdraw(amount);

}

public void printBalance() {

System.out.println(Thread.currentThread().getName()

+ " : TransactionType: " + this.transactionType + ", Amount: "

+ this.amount);

System.out.println("Account Balance: "

+ this.account.getAccountBalance());

}

}

class Account {

private int accountNumber;

private double accountBalance;

public int getAccountNumber() {

return accountNumber;

}

public double getAccountBalance() {

return accountBalance;

}

public Account(int accountNumber) {

this.accountNumber = accountNumber;

}

// If this method is not synchronized, you will see race condition on

// Remove syncronized keyword to see race condition

public synchronized boolean deposit(double amount) {

if (amount < 0) {

return false;

} else {

accountBalance = accountBalance + amount;

return true;

}

}

// If this method is not synchronized, you will see race condition on

// Remove syncronized keyword to see race condition

public synchronized boolean withdraw(double amount) {

if (amount > accountBalance) {

return false;

} else {

accountBalance = accountBalance - amount;

return true;

}

}

}

#4楼

竞争条件和数据竞争之间存在重要的技术差异。 大多数答案似乎都假设这些术语是等效的,但事实并非如此。

当2条指令访问相同的存储器位置时发生数据争用,这些访问中的至少一个是写操作,并且在这些访问之间进行排序之前没有发生任何情况 。 现在,关于在顺序之前发生的事件的争论很多,但是通常在同一锁定变量上的ulock-lock对和在同一条件变量上的wait-signal对会导致发生先于顺序。

竞争条件是语义错误。 这是在事件的时间安排或顺序中出现的缺陷,导致错误的程序行为 。

许多竞争条件可能是(实际上是)数据竞争引起的,但这不是必需的。 实际上,数据争用和争用条件既不是彼此的必要条件也不是充分条件。 这篇博客文章还通过一个简单的银行交易示例很好地解释了差异。 这是另一个简单的示例 ,解释了它们之间的区别。

现在我们已经确定了术语,让我们尝试回答原始问题。

由于种族条件是语义错误,因此没有检测它们的通用方法。 这是因为在通常情况下,无法使用自动的oracle来区分正确的程序行为与错误的程序行为。 种族检测是一个无法确定的问题。

另一方面,数据竞争具有不一定与正确性相关的精确定义,因此人们可以检测到它们。 数据争用检测器有很多类型(静态/动态数据争用检测,基于锁集的数据争用检测,基于事前发生的数据争用检测,混合数据争用检测)。 最先进的动态数据竞争检测器是ThreadSanitizer ,在实践中效果很好。

通常,处理数据争用需要一定的编程纪律来诱发(在开发期间或使用上述工具检测到它们之间)访问共享数据之间的边缘之前。 这可以通过锁,条件变量,信号量等来完成。但是,也可以采用不同的编程范例,例如消息传递(而不是共享内存)来避免构造过程中的数据争用。

#5楼

什么是比赛条件?

您打算在下午5点去看电影。 您在下午4点询问门票的供应情况。 该代表说,他们有空。 放映前5分钟,您可以放松身心并到达售票窗口。 我敢肯定,您可以猜测会发生什么:这是一间完整的房子。 这里的问题在于检查和操作之间的持续时间。 您在4咨询并在5采取行动。与此同时,其他人则抢了票。 那是比赛条件-特别是比赛条件的“先检查后行动”场景。

您如何检测到它们?

宗教代码审查,多线程单元测试。 没有捷径。 很少有Eclipse插件出现,但是还没有稳定的东西。

您如何处理和预防它们?

最好的办法是创建无副作用的无状态函数,并尽可能多地使用不可变对象。 但这并不总是可能的。 因此,使用java.util.concurrent.atomic,并发数据结构,正确的同步以及基于actor的并发性将有所帮助。

最佳的并发资源是JCIP。 您还可以在此处获得有关上述说明的更多详细信息 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值