并发程序的特性--原子性

114 阅读1分钟

线程的原子性

public class T00_IPlusPlus {
    private static long n = 0L;
    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[100];
        CountDownLatch latch = new CountDownLatch(threads.length);
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    //synchronized (T00_IPlusPlus.class) {
                    n++;
                    //}
                }
                latch.countDown();
            });
        }
        for (Thread t : threads) {
            t.start();
        }
        latch.await();
        System.out.println(n);
    }
}

1.一些基本概念

race condition => 竞争条件 , 指的是多个线程访问共享数据的时候产生竞争

数据的不一致(unconsistency),并发访问之下产生的不期望出现的结果

如何保障数据一致呢?--> 线程同步(线程执行的顺序安排好),

monitor (管程) ---> 锁

critical section -> 临界区

如果临界区执行时间长,语句多,叫做 锁的粒度比较粗,反之,就是锁的粒度比较细

具体: 保障操作的原子性(Atomicity)

  1. 悲观的认为这个操作会被别的线程打断(悲观锁)synchronized(上一个小程序)
  2. 乐观的认为这个做不会被别的线程打断(乐观锁 自旋锁 无锁)cas操作 CAS = Compare And Set/Swap/Exchange

image.png

2.上锁的本质

(1)上锁的本质是把并发编程序列化

(2) 保障可见性注意序列化并非其他程序一直没机会执行,而是有可能会被调度,但是抢不到锁,又回到Blocked或者Waiting状态(sync锁升级)一定是锁定同一把锁

3.JVM中的两种锁

重量级锁(经过操作系统的调度)synchronized早期都是这种锁

轻量级锁(CAS的实现,不经过OS调度)(无锁 - 自旋锁 - 乐观锁)

4.两种锁的效率

不同的场景:

临界区执行时间比较长 , 等的人很多 -> 重量级

时间短,等的人少 -> 自旋锁

5.synchronized如何保障可见性

image.png