设为首页 加入收藏

TOP

Java高并发之无锁与Atomic源码分析(二)
2018-06-09 10:07:57 】 浏览:972
Tags:Java 并发 Atomic 源码 分析
tem.out.println(i);
    }
}


Unsafe类是在sun.misc包下, 可以用于一些非安全的操作,比如:


根据偏移量设置值, 线程park(), 底层的CAS操作等等.


1 // 获取类实例中变量的偏移量
2 valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
3 // 基于偏移量对值进行操作
4 unsafe.compareAndSwapInt(this, valueOffset, expect, update);


主要接口


 


// 获得给定对象偏移量上的int值
public native int getInt(Object o, long offset);
// 设置给定对象偏移量上的int值
public native void putInt(Object o, long offset, int x);
// 获得字段在对象中的偏移量
public native long objectFieldOffset(Field f);
// 设置给定对象的int值,使用volatile语义
public native void putIntVolatile(Object o, long offset, int x);
// 获得给定对象对象的int值,使用volatile语义
public native int getIntVolatile(Object o, long offset);
// 和putIntVolatile()一样,但是它要求被操作字段就是volatile类型的
public native void putOrderedInt(Object o, long offset, int x);


与AtomicInteger类似, 只是里面封装了一个对象, 而不是int, 对引用进行修改


主要接口


1 get()
2 set(V)
3 compareAndSet()
4 getAndSet(V)


Demo


使用10个线程, 同时尝试修改AtomicReference中的String, 最终只有一个线程可以成功.


import java.util.concurrent.atomic.AtomicReference;


public class AtomicReferenceTest {
    public final static AtomicReference<String> attxnicStr = new AtomicReference<String>("abc");


    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread() {
                public void run() {
       

            try {
                        Thread.sleep(Math.abs((int) (Math.random() * 100)));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (attxnicStr.compareAndSet("abc", "def")) {
                        System.out.println("Thread:" + Thread.currentThread().getId() + " change value to " + attxnicStr.get());
                    } else {
                        System.out.println("Thread:" + Thread.currentThread().getId() + " change failed!");
                    }
                }
            }.start();
        }
    }
}


也是封装了一个引用, 主要解决ABA问题.


ABA问题


线程一准备用CAS将变量的值由A替换为B, 在此之前线程二将变量的值由A替换为C, 线程三又将C替换为A, 然后线程一执行CAS时发现变量的值仍然为A, 所以线程一CAS成功.


主要接口


// 比较设置 参数依次为:期望值 写入新值 期望时间戳 新时间戳
public boolean compareAndSet(V expectedReference,V newReference,int expectedStamp,int newStamp)
// 获得当前对象引用
public V getReference()
// 获得当前时间戳
public int getStamp()
// 设置当前对象引用和时间戳
public void set(V newReference, int newStamp)


源码分析


// 内部封装了一个Pair对象, 每次对对象操作的时候, stamp + 1
    private static class Pair<T> {
        final T reference;
        final int stamp;
        private Pair(T referen
编程开发网

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 2/10/10
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇JDK并发包详细总结 下一篇Java内存模型与指令重排

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

array(4) { ["type"]=> int(8) ["message"]=> string(24) "Undefined variable: jobs" ["file"]=> string(32) "/mnt/wp/cppentry/do/bencandy.php" ["line"]=> int(217) }