线程学习笔记-AtomicInteger类

AtomicIntege解决以下三个问题

  • 可见性
  • 有序性
  • 原子性

compareAndSet使用的是cpu级别的加锁

volatile只能保证可见性和有序性,但是不能保证原子性,代码如下:

public class AtomicIntegerTest {

    private volatile static int value = 1;

    private static Set<Integer> set = Collections.synchronizedSet(new HashSet<>());

    public static void main(String[] args) throws InterruptedException{
        Thread t1 = new Thread() {
            @Override
            public void run() {
                int x = 1;
                while (x <= 50000) {
                    set.add(value);
                    int tmp = value;
                    System.out.println(Thread.currentThread().getName() + ":" + tmp);
                    value += 1;
                    x++;
                }
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                int x = 1;
                while (x <= 50000) {
                    set.add(value);
                    int tmp = value;
                    System.out.println(Thread.currentThread().getName() + ":" + tmp);
                    value += 1;
                    x++;
                }
            }
        };
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println(set.size());
    }
}

应该是10000
在这里插入图片描述

AtomicInteger可以保证原子性,可见性和有序性(private volatile int value;)

public class AtomicIntegerTest {
    private volatile static int value;

    private static Set<Integer> set = Collections.synchronizedSet(new HashSet<>());

    public static void main(String[] args) throws InterruptedException{
        AtomicInteger atomicInteger = new AtomicInteger(1);
        Thread t1 = new Thread() {
            @Override
            public void run() {
                int x = 1;
                while (x <= 50000) {
                    int v = atomicInteger.getAndIncrement();
                    set.add(v);
                    System.out.println(Thread.currentThread().getName() + ":" + v);
                    x++;
                }
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                int x = 1;
                while (x <= 50000) {
                    int v = atomicInteger.getAndIncrement();
                    set.add(v);
                    System.out.println(Thread.currentThread().getName() + ":" + v);
                    x++;
                }
            }
        };
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(set.size());
    }
}

在这里插入图片描述

利用compareAndSet的特性来实现一个显示的锁,不同于synchronized的是,当没有抢到锁的线程会立即失败,而不是blocked住

package com.picc.concerrent3.chapter1;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 通过compareAndSet的特性实现一个锁
 */
public class CompareAndSetLock {

  private final AtomicInteger value = new AtomicInteger(0);

  private Thread lockThread;

  public void tryLock() throws GetLockException{
    boolean success = value.compareAndSet(0, 1);
    if(!success){
      throw new GetLockException("get the lock failed");
    } else {
      lockThread = Thread.currentThread();
    }
  }

  public void unlock(){
    if (0==value.get()) {
      return;
    }
    if (lockThread == Thread.currentThread())
      value.compareAndSet(1, 0);
  }
}


package com.picc.concerrent3.chapter1;

public class AtomicIntegerDetailTest2 {

  private final static CompareAndSetLock lock = new CompareAndSetLock();

  public static void main(String[] args) {
    for(int i=0;i<5;i++){
      new Thread(){
        @Override
        public void run() {
          try {
//            doSomething();
            doSomething2();
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }.start();
    }
  }

  private static void doSomething() throws InterruptedException{
    synchronized (AtomicIntegerDetailTest2.class){
      System.out.println(Thread.currentThread().getName()+" get the lock");
      Thread.sleep(100000);
    }
  }

  private static void doSomething2() throws Exception{
    try{
      lock.tryLock();
      System.out.println(Thread.currentThread().getName()+" get the lock");
      Thread.sleep(100000);
    }finally {
      lock.unlock();
    }
  }
}

在这里插入图片描述
AtomicInteger类源码

 	private volatile int value;
    static {
        try {
        	// 获取value对应的值在内存中的偏移量
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    // 原子自增 
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

Unsafe类源码

    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            // 首先获取value对应的内存中的值
            var5 = this.getIntVolatile(var1, var2);
        // var5 是预期值   var5 + var4是待更新值
        // var1(当前对象)和var2(代表偏移量)可以确定一个内存中的值,和var5预期值进行比较,如果一直,就更新为待更新值,退出自旋,如果不一致,重新获取内存中的值
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值