Java并发编程之竞争条件和临界区

概述

竞态条件是可能发生在临界区中的特殊条件。临界段是由多个线程执行的代码段,其中线程的执行顺序会影响临界段并发执行的结果。
当多个线程执行一个临界区的结果可能因线程执行的顺序而有所不同时,临界区被称为包含一个竞争条件。术语竞态条件源于这样一种比喻,即线程在临界区中竞态的结果会影响临界区的执行结果。

竞争条件

在同一个应用程序中运行多个线程本身不会导致问题。当多个线程访问相同的资源时,问题就出现了。例如相同的内存(变量、数组或对象)、系统(数据库、web服务等)或文件。
事实上,只有在一个或多个线程写入这些资源时才会出现问题。只要资源不改变,让多个线程读取相同的资源是安全的。
我们创建一个Timer.java进行验证竞争的关系:代码如下:

/**
 * 记录次数
 */
public class Timer{
    protected long timer;
    public void add(long value){
        this.timer += value;
    }
}

我们这里想的结果是5,但是和结果不相符,这里为2.这里发生了线程的竞争关系。
操作流程:

     * timer初始化为0
     * 
     * thread01 -> add(2) -> 2
     * thread02 -> add(3) -> 3
     * 这两个线程希望将值2和3添加到计数器中。
     * 因此,在两个线程完成执行后,值应该是5。
     * 但是,由于这两个线程的执行是交错的,所以最终的结果是不同的

在临界区中的竞争条件

add()方法中的代码包含一个临界区。当多个线程执行此临界区时,将出现竞争条件。更正式的情况是,两个线程竞争相同的资源,其中访问资源的顺序很重要,称为竞争条件。导致竞争条件的代码段称为临界段。

防止竞争条件

为了防止出现竞态条件,必须确保临界区作为原子指令执行。这意味着一旦一个线程执行它,其他线程就不能执行它,直到第一个线程离开临界区。
通过在关键区域中进行适当的线程同步,可以避免竞争条件。线程同步可以通过使用一个同步的Java代码块来实现。线程同步也可以通过使用其他同步结构(如LOCK)或原子变量(如java.util.concurrent. AtomicInteger)来实现.

临界区的吞吐量

对于较小的临界区,使整个临界区成为一个同步块可以工作。但是,对于较大的临界区,将临界区分解为较小的临界区可能是有益的,以允许多个线程执行每个较小的临界区。这可能会减少对共享资源的争用,从而增加总临界区的吞吐量.代码如下:

	public class TwoNumSums {
    private int sum1 = 0;
    private int sum2 = 0;
    public void add(int val1, int val2){
        synchronized(this){
            this.sum1 += val1;   
            this.sum2 += val2;
        }
    }
}

注意add()方法是如何将值添加到两个不同的sum成员变量的。为了防止竞态条件,要在Java同步块中执行求和。在这个实现中,只有一个线程可以同时执行求和
但是,由于这两个sum变量是相互独立的,您可以将它们的sum分解成两个独立的同步块,代码如下:

	public class TwoNumSums {
    
    private int sum1 = 0;
    private int sum2 = 0;

    private Integer sum1Lock = new Integer(1);
    private Integer sum2Lock = new Integer(2);

    public void add(int val1, int val2){
        synchronized(this.sum1Lock){
            this.sum1 += val1;   
        }
        synchronized(this.sum2Lock){
            this.sum2 += val2;
        }
    }
}

现在两个线程可以同时执行add()方法。一个线程在第一个同步块中,另一个线程在第二个同步块中。这两个同步块在不同的对象上同步,因此两个不同的线程可以独立地执行这两个块。这样,线程之间执行add()方法的等待时间就会减少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值