Java多线程基础总结五:atomic

在简单介绍java.util.concurrent.atomic包之前,有个概念要先抄袭熟悉一遍:CAS(比较并交换)。现在大多数的处理器都提供对并发 访问的支持,这个支持的反映方式就是提供硬件的指令支持多处理的特殊需求。比如检测或者阻止其它处理器的并发访问来更新共享变量的 指令。对于 Intel x86架构的处理器来说就是通过提供实现CAS或者比较并设置的硬件原语指令集。CAS操作的三个操作数:内存位置(V) ,预期原值(A)和新值(B)。执行的过程通常是:预测内存地址V应该包含值A,如果包含则将值B替换到位置V;否则,不更改任何值,告 知地址V的当前值。CAS对待“读-修改-写”的操作一般是检测这个过程是否有其它的线程在修改变量,如果有那么这次的CAS操作失败, 可以尝试重新进行CAS。讲到这里似乎感觉比 Synchronized还复杂,是否意味着成本不小呢?答案是否。因为它是硬件原生实现的,极为轻 量级的无锁同步方式。就好像高清解码一样,GPU原生硬件解码比软解的CPU占用优势那是相当的不一样啊!

说到硬件我就想到最近狂能争论的使用64位操作系统的优势。现在处理器多数支持64位,意味着处理器的寄存器映射到内存的寻址空间 大大的大了,操作系统 64位的架构或许在内存管理上的挑战更大了,没有好的内存压缩技术,大内存只能是大浪费。同时还表示如果三方 软件开发者对64位系统内存管理不熟悉,软件变垃圾的概率变大了。没有好的64位三方软件的繁荣,操作系统仅仅作为一个支撑软件运行的 平台能干什么呢?所以使用优势不在操作系统本身而在于平台之上的软件。又扯远了,哎...

JDK5以后在java.util.concurrent.atomic包下提供了十几个原子类。常见的是 AtomicInteger,AtomicLong,AtomicReference以及它们 的数组形式,还有AtomicBoolean和为了处理 ABA问题引入的AtomicStampedReference类,最后就是基于反射的对volatile变量进行更新的 实用工具类:AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceFieldUpdater。这些原子类理论上能够大幅的提升性 能。并且java.util.concurrent内的并发集合,线程池,执行器,同步器的内部实现大量的依赖这些无锁原子类,从而争取性能的最大化。 下面通过一个简单的例子看看:

Java代码

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicInteger;

/**
  * User: yanxuxin
  * Date: Dec 16, 2009
  * Time: 10:49:40 PM
  */
public class AtomicCounterSample extends Thread {
   private AtomicCounter atomicCounter;

   public AtomicCounterSample(AtomicCounter atomicCounter) {
     this.atomicCounter = atomicCounter;
   }

   @Override 
   public void run() {
     long sleepTime = (long) (Math.random() * 100);
     try {
       Thread.sleep(sleepTime);
     } catch (InterruptedException e) {
       e.printStackTrace();
     }

     atomicCounter.counterIncrement();
   }

   public static void main(String[] args) throws Exception {
     AtomicCounter atomicCounter = new AtomicCounter();

     for (int i = 0; i < 5000; i++) {
       new AtomicCounterSample(atomicCounter).start();
     }

     Thread.sleep(3000);

     System.out.println("counter=" + atomicCounter.getCounter());
   }
}

class AtomicCounter {
   private AtomicInteger counter = new AtomicInteger(0);

   public int getCounter() {
     return counter.get();
   }

   public void counterIncrement() {
     for (; ;) {
       int current = counter.get();
       int next = current + 1;
       if (counter.compareAndSet(current, next))
         return;
     }
   }
}

class AtomicCounter2 {
   private volatile int counter;
   private static final AtomicIntegerFieldUpdater<AtomicCounter2> counterUpdater =  AtomicIntegerFieldUpdater.newUpdater(AtomicCounter2.class, "counter");

   public int getCounter() {
     return counter;
   }

   public int counterIncrement() {
//    return counter++;
     return counterUpdater.getAndIncrement(this);
   }
}

时间: 2024-09-17 04:21:36

Java多线程基础总结五:atomic的相关文章

Java多线程基础总结七:ReentrantLock

之前总结了部分无锁机制的多线程基础,理想的状态当然是利用无锁同步解决多线程程序设计的问题.但是实际碰到的问题使得很多情 况下,我们不得不借助锁同步来保证线程安全.自从JDK5开始,有两种机制来屏蔽代码块在并行访问的干扰,synchronized关键字已经介绍 过了部分内容,所以这次简单的说说另一种锁机制:ReentrantLock. 对于synchronized的缺点之前也简单的说了一些,实际使用中比较烦扰的几点是:a.只有一个"条件"与锁相关联,这对于大量并发线程 的情况是很难管理(

多线程基础(五)NSThread线程通信

5.多线程基础 线程间通信 什么叫线程间通信 在一个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另一个线程 在1个线程中执行完特定任务后, 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 线程间通信常用方法 perform执行 selector选择器 - (void)performSelectorOnMainThread:(SEL)aSelectorwithObject:(id)arg

Java多线程基础总结三: volatile

前面的两篇总结简单的说明了同步的一些问题,在使用基础的同步机制中还有两个可以分享的技术:volatile关键字和ThreadLocal.合 理的根据场景利用这些技术,可以有效的提高并发的性能,下面尝试结合自己的理解叙述这部分的内容,应该会有理解的偏差,我也会尽量 的在完善自己理解的同时同步更新文章的错误. 或许在知道synchronized配和对象内部锁的机制以后,可以提高写出正确同步的并发程序成功率,但是这时候会遇到另一个大问题:性 能!是的,对于 synchronized带来的可能庞大的性能

Java多线程基础总结八:ReentrantReadWriteLock

说到ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限.它和后者都是单独的实现,彼此之间没有继承或实现的关系. 然后就是总结这个锁机制的特性了: (a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想. (b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的

Java多线程基础总结九:Mina窥探(1)

一直以来的多线程的基础总结都是脱离应用的,但是要说多线程的应用就不能不说Mina.Apache Mina作为一个高性能的Java异步并发网 络通讯框架,其内部的多线程的设计和实现可谓是学习多线程的良药.手上的Mina源码是svn剪下来的最新的代码,mvn转化成eclipse项目 后导入mina-core的源码看看多线程的应用吧. 首先简单的介绍在org.apache.mina.core.service包里的核心接口之一:IoService.这个接口是对于服务器端接收连接和客户端发起连 接这两种服

Java多线程基础总结四:ThreadLocal

说到ThreadLocal,首先说说这个类的命名.直观上看好像是个Thread的什么亲戚,但其实它想表达的意思是线程本地变量,也就是说每 个线程自己的变量.它作为一个JDK5以后支持范型的类,主要是想利用范型把非线程安全的共享变量,封装成绑定线程的安全不共享变量. 这样的解释我想我们多半能猜出它的实现思路:把一个共享变量在每个线程使用时,初始化一个副本,并且和线程绑定.以后所有的线程对 共享变量的操作都是对线程内部那个副本,完全的线程内部变量的操作. 要实现这样功能类的设计,主要技术点是要能把副

Java多线程基础总结一: synchronized(1)

最近写关于并发的小应用,才发现真的该好好的正视java的多线程了.之前没有深入的掌握,用起来也是那么的吃力.作为J2SE里面为 数不多的重要难点之一,多线程应用一直是我以敬畏的心态去尽量避开的,只是通过一些实例掌握一些简单的应用.这段时间会多用点时间 去掌握,有需要写下来的我也会通过这种方式既分享又加深理解. 首先这篇只涉及基础的知识整理,对于并发包java.util.concurrent内的线程池和锁我会看情况在之后的总结中写点东西.对于进程的 概念我们都很熟悉,它是应用程序级的隔离,不同的应

java:多线程基础之Runnable、Callable与Thread

java.lang包下有二个非常有用的东西:Runnable接口与Thread类,Thread实现了Runnable接口(可以认为Thread是Runnable的子类),利用它们可以实现最基本的多线程开发. 一.Runnable入门示例 1 public class RunnableDemo1 { 2 3 public static void main(String[] args) { 4 new Runnable() { 5 public void run() { 6 for (int i =

java多线程基础(synchronize关键字)

基础知识 多线程实现方法 使用Thread创建线并启动线程 使用Runnable创建并启动线程 使用内部类创建线程 线程的方法 线程优先级 守护线程 sleep方法 yield方法 join方法 线程同步 基础知识 线程:进程(process)就是一块包含了某些资源的内存区域.操作系统利用进程把它的工作划分为一些功能单元. 线程:进程中所包含的一个或多个执行单元称为线程(thread).进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问. 线程和进程的区别如下: 1)一个进程至少有