Java并发控制synchronized与AtomicInteger类

众所周知,在Java多线程编程中,一个非常重要的方面就是线程的同步问题。关于线程的同步,最常用的解决方法就是使用synchronized关键字,但是如果使用场景只用在控制一个计数的整型变量时(通常这也是非常常见的一个使用场景),另一种实现方式AtomicInteger类简洁易用的特性一定会让你对它爱不释手。
我们先通过一个简单的例子模拟下多线程并发计数,程序如下

public class ShareData {
	public static int count=0;
	public static void main(String[] args){
		final ShareData data  = new ShareData();
		for(int i=0;i<10;i++){
			new Thread(
					new Runnable(){
						public void run(){
							try{
								Thread.sleep(1);
							}catch(InterruptedException e){
								e.printStackTrace();
							}
							for(int j=0;j<100;j++){
								data.addCount();
							}
							System.out.print(count+" ");
						}
					}
				).start();				
		}
		try{
			Thread.sleep(3000);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		System.out.print("count="+count);
	}
	public void addCount(){
		count++;
	}
}


程序启动了十个线程,每个线程计100次数,操作的都是count这个变量,最后在等待3秒(所有线程均执行结束后)输出此时的count值,每次执行后的输出结果都不一定一样,但是一般count小于1000,结果如下:


100 224 373 473 373 255 823 791 691 591 count=823

344 566 366 299 299 466 366 669 695 769 count=769

400 400 400 500 400 615 913 813 713 713 count=913


我们将addCount()方法加上synchronized关键词修饰下,让它实现线程安全,

	public synchronized void addCount(){
		count++;
	}


再执行,结果如下:

200 200 411 677 774 864 1000 666 1000 891 count=1000

423 909 1000 428 802 512 691 706 512 914 count=1000

300 500 500 300 300 712 809 850 949 1000 count=1000

此时可以看出最终count的数值都会精确的是1000,讲完了synchronized之后我们再来看下AtomicInteger类

AtomicInteger类可以用原子方式更新的 int 值,主要用于在高并发环境下的高效程序处理,使用非阻塞算法来实现并发控制,它的方法有

//获取当前的值
public final int get()
//取当前的值,并设置新的值
public final int getAndSet(int newValue)
//获取当前的值,并自增
public final int getAndIncrement() 
//获取当前的值,并自减
public final int getAndDecrement()
//获取当前的值,并加上预期的值
public final int getAndAdd(int delta) 
这里我们依然用上面的程序做例子,使用AtomicInteger类来替代synchronized方式,代码如下:

package concurrent;

import java.util.concurrent.atomic.AtomicInteger;

public class ShareData_AtomicInteger {
	static AtomicInteger count = new AtomicInteger(0);
	public static void main(String[] args){
		final ShareData_AtomicInteger data  = new ShareData_AtomicInteger();
		for(int i=0;i<10;i++){
			new Thread(
					new Runnable(){
						public void run(){
							try{
								Thread.sleep(1);
							}catch(InterruptedException e){
								e.printStackTrace();
							}
							for(int j=0;j<100;j++){
								data.addCount();
							}
							System.out.print(count.get()+" ");
						}
					}
				).start();				
		}
		try{
			Thread.sleep(3000);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		System.out.print("count="+count.get());
	}
	public void addCount(){
		count.getAndIncrement();
	}
}




 

执行结果如下:

495 528 604 504 987 657 741 682 1000 925 count=1000

500 500 984 823 499 733 500 495 601 1000 count=1000

409 409 436 409 700 587 600 872 988 1000 count=1000

至此结束,AtomicInteger只是concurrent下的一个整数原子操作类,该包下还有很多其他关于线程锁同步的机制,有兴趣的同学可以自行搜索下相关资料~谢谢

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java并发编程是指在Java程序中使用多线程实现并发执行的编程技术。它能有效利用多核处理器的优势,提升程序的性能和响应能力。以下是Java并发编程的基础知识: 1. 线程与进程:Java中的线程是程序中执行的最小单位,线程共享进程的资源,包括内存空间和文件等。多线程可以同时执行不同的任务,相比单线程能更高效地利用系统资源。 2. 线程创建:Java中创建线程有两种方式,一种是继承Thread,实现run()方法;另一种是实现Runnable接口,重写run()方法。通过调用start()方法启动线程。 3. 线程同步:多个线程在访问共享资源时可能会产生竞争条件,可能会导致数据不一致或者出现死锁等问题。通过使用同步机制来保证线程安全,例如使用synchronized关键字实现对共享资源的互斥访问。 4. 线程通信:线程之间可以通过共享变量来进行通信。使用wait()、notify()和notifyAll()方法实现线程的等待和唤醒。 5. 线程池:线程池是一种管理线程的机制,可以有效控制线程的数量和复用线程资源,避免频繁创建销毁线程的开销。 6. 并发容器:Java提供了一些线程安全的数据结构,如ConcurrentHashMap和ConcurrentLinkedQueue等,用于在多线程环境下安全地操作数据。 7. 原子操作:Java提供了一些原子操作,如AtomicIntegerAtomicLong等,它们能够保证对共享数据的操作是原子的,不会发生数据不一致的情况。 8. 同步工具Java提供了一些同步工具,如CountDownLatch和CyclicBarrier等,用于控制线程的执行顺序和线程之间的同步。 以上是Java并发编程的基础知识,掌握了这些知识可以更好地利用多线程来提高程序的性能和并发能力。同时也需要注意并发编程可能带来的线程安全问题,合理使用同步机制和并发容器等工具来保证程序的正确运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值