Java并发编程中如何保证原子性

原子性,可见性,有序性是并发的三大特征,所谓原子性,就是一个操作要么全部执行,要么都不执行。

如下所示,在一个类中,定义一个静态变量int var=0,现在开启20个线程,每个线程都执行相同的操作,即对var实行10000次++操作,线程退出,然后打印var的值。

package com.xxx.cas;

public class PlusPlusOP {
	public static int var = 0;
	
	public static void plusAndPlus(){
		var++;
	}
	
	public static void main(String[] args) {
		Thread threads[] = new Thread[20];
		for(int i=0;i<20;i++){
			threads[i] = new Thread(new Runnable() {
				
				@Override
				public void run() {
					for(int i=0;i<10000;i++){	
						plusAndPlus();
					}
				}
			});
			threads[i].start();
		}
		
		while(Thread.activeCount()>1){
			Thread.yield();
		}
		System.out.println("var=>"+var);
	}
}

默认,没有对原子操作做特殊的处理,我们的到的结果各种各样,但就不是200000。如下所示:

这是一个很常见的并发问题,涉及到的是原子操作,var++这个动作,其实分为了三个过程:

  1. 读取var的值
  2. ++操作
  3. 写入var的值 

多线程并发的情况下,有可能第一个线程获取了var=10000,即将执行++操作,这时候另一个线程也来获取var,这时候获取的应该也是10000,当他们都执行完成的时候,本来应该是10002,但是实际上,因为并发的原因,导致了最终的结果是10001。所以我们看到的结果是一个小于200000的数字,程序在这种情况下运行,得到这个结果是正常的。再次运行,可能还是一个小于200000的结果。

那么如何解决这个原子性的问题呢,其实就是要保证var++这个动作不能被拆开,一旦进入读取var的值,那么接下来只有执行了写入var的值之后,别的线程才可以运行读取var的值操作。这就需要var++这个操作是同步的,解决办法可以有如下三种:

  • synchronized同步代码块
  • cas原子类工具
  • lock锁机制

三种解决方案的具体实现:

synchronized同步代码块

cas原子类工具

lock锁

 

   

    上面介绍的三种方式,解决并发编程中原子问题,使用synchronized关键字是最简单的,对代码的修改是最小的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值