Java多线程:原子量

所谓的原子量即操作变量的操作是“原子的”,该操作不可再分,因此是线程安全的。

为何要使用原子变量呢,原因是多个线程对单个变量操作也会引起一些问题。在Java5之前,可以通过volatile、synchronized关键字来解决并发访问的安全问题,但这样太麻烦。

Java5之后,专门提供了用来进行单变量多线程并发安全访问的工具包java.util.concurrent.atomic,其中的类也很简单。

主要有:

AtomicBoolean

AtomicInteger

AtomicIntegerArray

AtomicIntegerFieldUpdater

AtomicLong

AtomicLongArray

AtomicLongFieldUpdater

AtomicMarkableReference

AtomicReference

AtomicReferenceArray

AtomicReferenceFieldUpdater

AtomicStampedReference

DoubleAccumulator

DoubleAdder

LongAccumulator

LongAdder

下面给出一个反面例子(切勿模仿):

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.atomic.AtomicLong;

/**

\* Java线程:新特征-原子量

*

\* @author leizhimin 2009-11-6 9:53:11

*/

publicclass Test {

publicstaticvoid main(String[] args) {

ExecutorService pool = Executors.newFixedThreadPool(2);

Runnable t1 = new MyRunnable("张三", 2000);

Runnable t2 = new MyRunnable("李四", 3600);

Runnable t3 = new MyRunnable("王五", 2700);

Runnable t4 = new MyRunnable("老张", 600);

Runnable t5 = new MyRunnable("老牛", 1300);

Runnable t6 = new MyRunnable("胖子", 800);

//执行各个线程

pool.execute(t1);

pool.execute(t2);

pool.execute(t3);

pool.execute(t4);

pool.execute(t5);

pool.execute(t6);

//关闭线程池

pool.shutdown();

}

}

class MyRunnable implements Runnable {

private static AtomicLong aLong =new AtomicLong(10000); //原子量,每个线程都可以自由操作

private String name; //操作人

private int x; //操作数额

​ MyRunnable(String name, int x) {

​ this.name = name;

​ this.x = x;

​ }

​ public void run() {

​ System.out.println(name + "执行了" + x +",当前余额:" + aLong.addAndGet(x));

​ }

}

运行结果:

李四执行了3600,当前余额:13600

王五执行了2700,当前余额:16300

老张执行了600,当前余额:16900

老牛执行了1300,当前余额:18200

胖子执行了800,当前余额:19000

张三执行了2000,当前余额:21000

Process finished with exit code 0

张三执行了2000,当前余额:12000

王五执行了2700,当前余额:18300

老张执行了600,当前余额:18900

老牛执行了1300,当前余额:20200

胖子执行了800,当前余额:21000

李四执行了3600,当前余额:15600

Process finished with exit code 0

张三执行了2000,当前余额:12000

李四执行了3600,当前余额:15600

老张执行了600,当前余额:18900

老牛执行了1300,当前余额:20200

胖子执行了800,当前余额:21000

王五执行了2700,当前余额:18300

Process finished with exit code 0

从运行结果可以看出,虽然使用了原子量,但是程序并发访问还是有问题,那究竟问题出在哪里了?

这里要注意的一点是,原子量虽然可以保证单个变量在某一个操作过程的安全,但无法保证你整个代码块,或者整个程序的安全性。因此,通常还应该使用锁等同步机制来控制整个程序的安全性。

下面是对这个错误修正:

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

import java.util.concurrent.atomic.AtomicLong;

/**

\* Java线程:新特征-原子量

*

\* @author leizhimin 2009-11-6 9:53:11

*/

publicclass Test {

publicstaticvoid main(String[] args) {

ExecutorService pool = Executors.newFixedThreadPool(2);

Lock lock = new ReentrantLock(false);

Runnable t1 = new MyRunnable("张三", 2000,lock);

Runnable t2 = new MyRunnable("李四", 3600,lock);

Runnable t3 = new MyRunnable("王五", 2700,lock);

Runnable t4 = new MyRunnable("老张", 600,lock);

Runnable t5 = new MyRunnable("老牛", 1300,lock);

Runnable t6 = new MyRunnable("胖子", 800,lock);

//执行各个线程

pool.execute(t1);

pool.execute(t2);

pool.execute(t3);

pool.execute(t4);

pool.execute(t5);

pool.execute(t6);

//关闭线程池

pool.shutdown();

}

}

class MyRunnableimplements Runnable {

privatestatic AtomicLong aLong =new AtomicLong(10000); //原子量,每个线程都可以自由操作

private String name; //操作人

privateint x; //操作数额

private Lock lock;

​ MyRunnable(String name, int x,Lock lock) {

​ this.name = name;

​ this.x = x;

​ this.lock = lock;

​ }

​ publicvoid run() {

​ lock.lock();

​ System.out.println(name + "执行了" + x +",当前余额:" + aLong.addAndGet(x));//原子操作仅仅是表示add这一个操作是原子的,这个复合操作却不一定

​ lock.unlock();

​ }

}

执行结果:

张三执行了2000,当前余额:12000

王五执行了2700,当前余额:14700

老张执行了600,当前余额:15300

老牛执行了1300,当前余额:16600

胖子执行了800,当前余额:17400

李四执行了3600,当前余额:21000

Process finished with exit code 0

这里使用了一个对象锁,来控制对并发代码的访问。不管运行多少次,执行次序如何,最终余额均为21000,这个结果是正确的。

有关原子量的用法很简单,关键是对原子量的认识,原子仅仅是保证变量操作的原子性,但整个程序还需要考虑线程安全的。

java 多线程 原子_Java多线程:原子量相关推荐

  1. java线程钥匙_Java多线程并发编程/锁的理解

    一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...

  2. java线程 教程_Java多线程系列教程

    Java多线程系列教程 多线程是Java中不可避免的一个重要主体.从本章开始,我们将展开对多线程的学习.接下来的内容是对Java多线程内容的讲解,涉及到的内容包括,Object类中的wait(), n ...

  3. java 多线程 总结_Java 多线程总结

    昨天熬了个通宵,看了一晚上的视频,把java 的多线程相关技术重新复习了一遍,下面对学习过程中遇到的知识点进行下总结. 首先我们先来了解一下进程.线程.并发执行的概念: 进程是指:一个内存中运行的应用 ...

  4. java线程入门_java多线程快速入门(一)

    1.什么是进程 比如:QQ.QQ游戏.eclipse都是进程,可以通过任务管理器查看进程 2.进程和线程区别 线程是进程的一部分,一个进程可以包含多个线程,一个线程只能属于一个进程 进程是所有线程的集 ...

  5. java 高效的多线程同步_java多线程的同步和异步

    java多线程的同步和异步 Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言.Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于PC.数据中心.游戏控制台.科学超级计算 ...

  6. java的多线程机制_Java多线程开发(一)| 基本的线程机制

    0. 前言 Java 为了实现跨平台,在语言层面上实现了多线程.我们只需要熟悉 Java 这一套多线程机制就行了,比 C/C++ 要容易多了. 1. 定义任务 我们编写程序,最终是为了完成特定的任务. ...

  7. java 线程分配_Java多线程原子引用分配

    我有一个缓存,该缓存是使用Simeple HashMap实现的.喜欢 - HashMap cache = new HashMap(); 大部分时间都使用此缓存从中读取值.我有另一个重新加载缓存的方法, ...

  8. java 锁竞争_Java多线程中的竞争条件、锁以及同步的概念

    竞争条件 1.竞争条件: 在java多线程中,当两个或以上的线程对同一个数据进行操作的时候,可能会产生"竞争条件"的现象.这种现象产生的根本原因是因为多个线程在对同一个数据进行操作 ...

  9. java volatile 死锁_Java 多线程:volatile 变量、happens-before 关系及内存一致性

    原标题:Java 多线程:volatile 变量.happens-before 关系及内存一致性 来源:ImportNew - paddx 更新 请参考来自 Jean-philippe Bempel ...

  10. java 优化线程_Java | 多线程调优(下):如何优化多线程上下文切换?

    通过上一讲的讲解,相信你对上下文切换已经有了一定的了解了.如果是单个线程,在 CPU 调用之后,那么它基本上是不会被调度出去的.如果可运行的线程数远大于 CPU 数量,那么操作系统最终会将某个正在运行 ...

最新文章

  1. 在jupyter中使用matlab
  2. 通过什么来衡量C# Socket服务的效能
  3. Linux 设置windows可见的文件夹共享,创建只拥有读权限的共享用户,samba工具安装,“smbpasswd: command not found“问题解决
  4. php7 出现Class 'DOMDocument' not found的解决方法
  5. Python中的异常处理详解
  6. 【SpringBoot MQ 系列】RabbitListener 消费基本使用姿势介绍
  7. 分布式系统:一致性模型
  8. thinkphp三级分销小程序源码_山东谷道微信小程序商城源码带后台 公众号平台三级分销系统...
  9. js字符串string转object对象 - 方法篇
  10. python魔法方法(一)
  11. SecureCRT终端仿真程序下载及安装使用
  12. Visual C# 2005 - 如何于DataGridView控件中以跨数据行方式显示数据
  13. python入门经典100例-【python】编程语言入门经典100例--37
  14. PSpice电路模拟
  15. js判断数组key是否存在
  16. 汽车如何打蜡 汽车打蜡有什么要注意的地方
  17. 测试固态硬盘寿命软件,为什么说耐久测试才是检验SSD寿命的关键
  18. H264和MPEG4区别
  19. 微信开发JS接口安全域名 网页授权域名 业务域名
  20. php 统计汉字,PHP 统计实时统计汉字个数和区别

热门文章

  1. php进程是什么,PHP的进程模型是什么
  2. conime.exe是什么?conime.exe病毒的清除方法
  3. 计算机操作系统发展史
  4. ITK VKT 安装-详细
  5. Maven之(七)pom.xml配置文件详解
  6. 计算机组装与维护公开课,计算机组装与维护公开课教案
  7. 【场景化解决方案】ERP系统与钉钉实现数据互通
  8. 某跳动面试官:说说微信扫码登录背后的实现原理?
  9. 手把手带你SQLite3快速入门
  10. SQL2008升级SQL2008R2完全教程