01-java锁

2020-08-12  本文已影响0人  格林哈

1 并发编程面临的问题

1.1 上下文切换

1.2 死锁

1.3 资源限制

2 乐观锁,悲观锁

2.1 悲观锁

2.2 乐观锁

3 Java并发底层实现原理

3.1 volatile

public class Main {
    private int m = 2;
    private static volatile String   istr = "istrValue";
    protected static volatile String   istr2 = "istrValue2";
    private final String finalX = "finalXValue";
    public static void main(String[] args) {
        istr = "21312";
        istr2 = "12312";
    }
}


0x01a3de1d: movb $0×0,0×1104800(%esi);0x01a3de24: lock addl $0×0,(%esp);
image.png
Main字节码

3.2 synchronized

public class SynchronizedEXample {
    static volatile int i = 0;
    static  Object o = new Object();
    public static synchronized void method1(){
       synchronized (SynchronizedEXample.class) {
           i++;
       }
    }
    public static synchronized void method2(){
        synchronized (o) {
            i++;
        }
    }
}
//method1  字节码指令
ldc指令int、float或String型常量从常量池推送至栈顶
astore_0 栈顶ref对象数值存入第1局部变量

  public static synchronized void method1();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=2, args_size=0
         0: ldc           #2                  // class com/mg/bfbcdys/chapter02/SynchronizedEXample
         2: dup
         3: astore_0
         4: monitorenter
         5: getstatic     #3                  // Field i:I
         8: iconst_1
         9: iadd
        10: putstatic     #3                  // Field i:I
        13: aload_0
        14: monitorexit
        15: goto          23
        18: astore_1
        19: aload_0
        20: monitorexit
        21: aload_1
        22: athrow
        23: return

4原子操作实现原理

//AtomicStampedReference  compareAndSet 方法
public boolean compareAndSet(V   expectedReference, //预期引用
                                 V   newReference, //更新后的引用
                                 int expectedStamp, // 预取的标志
                                 int newStamp)  // 更新后的标志

// AtomicInteger 自增方法
public final int incrementAndGet() {
  return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}

// Unsafe.class
public final int getAndAddInt(Object o, long offset, int expected) {
  int var5;
  do {
      var5 = this.getIntVolatile(o, offset);
  } while(!this.compareAndSwapInt(o, offset, var5, var5 + expected));
  return var5;
}


public class AtomicIntegerExample {
    static AtomicInteger atomicInteger = new AtomicInteger(0);
    public static void main(String[] args) throws Exception {
        System.out.println(ClassLayout.parseClass(AtomicInteger.class).toPrintable());
        Unsafe unsafe = getUnsafeInstance();
        System.out.println("=================");

        long offset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
        atomicInteger.incrementAndGet();
        int va = unsafe.getInt(atomicInteger,offset);
        System.out.println("va: " + va);
        System.out.println("atomicInteger:"+atomicInteger);
    }

    public static Unsafe getUnsafeInstance() throws Exception {
        // 通过反射获取rt.jar下的Unsafe类
        Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafeInstance.setAccessible(true);
        // return (Unsafe) theUnsafeInstance.get(null);是等价的
        return (Unsafe) theUnsafeInstance.get(Unsafe.class);
    }
}
// 输出
java.util.concurrent.atomic.AtomicInteger object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0    12        (object header)                           N/A
     12     4    int AtomicInteger.value                       N/A
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

=================
va: 1
atomicInteger:1

// -XX:-UseCompressedOops 去掉指针压缩后的输出
java.util.concurrent.atomic.AtomicInteger object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0    16        (object header)                           N/A
     16     4    int AtomicInteger.value                       N/A
     20     4        (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

=================
va: 1
atomicInteger:1

参考
java并发编程的艺术
美团博客
https://github.com/farmerjohngit/myblog/issues/12

上一篇 下一篇

猜你喜欢

热点阅读