package com.gzs.learn.juc.base;

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

import org.junit.Test;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 原子操作示例
 *
 * @author guanzhisong
 * @date 2017年11月4日
 */
@Slf4j
public class AtomicExample {
    @Test
    public void testAtomic() throws InterruptedException {
        Counter counter = new Counter();
        int threadCount = 100;
        CountDownLatch startLatch = new CountDownLatch(1);
        CountDownLatch waitLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            new ExampleThread(counter, startLatch, waitLatch).start();
        }
        startLatch.countDown();
        waitLatch.await();
        log.info("not thread safe counter:{}", counter.getCount());
        log.info("thread safe counter:{}", counter.getAtomicCounter().get());
    }
}


@Data
class Counter {
    private int count;
    private AtomicInteger atomicCounter;

    public Counter() {
        count = 0;
        atomicCounter = new AtomicInteger(0);
    }

    public void notSafeCount() {
        count++;
    }

    public synchronized void safeCount() {
        count++;
    }

    public void atomicCount() {
        atomicCounter.incrementAndGet();
    }
}


@AllArgsConstructor
class ExampleThread extends Thread {
    private static final int LOOP_TIMES = 100;
    private Counter counter;
    private CountDownLatch startLatch;
    private CountDownLatch waitLatch;

    @Override
    public void run() {
        try {
            startLatch.await();
            for (int i = 0; i < LOOP_TIMES; i++) {
                counter.notSafeCount();
                counter.atomicCount();
            }
        } catch (InterruptedException e) {
        } finally {
            waitLatch.countDown();
        }
    }
}

@@ -440,24 +440,39 @@
  Counter();%0A
+        // %E7%BA%BF%E7%A8%8B%E6%95%B0%0A
         int 
@@ -486,24 +486,84 @@
 ount = 100;%0A
+        // %E5%8F%AF%E4%BB%A5%E5%85%88%E4%B8%8D%E7%94%A8%E7%90%86%E4%BC%9A%E8%BF%99%E4%B8%A4%E4%B8%AA%E7%B1%BB,%E6%AD%A4%E5%A4%84%E7%94%A8%E9%80%94%E6%98%AF%E7%A1%AE%E4%BF%9D%E7%BA%BF%E7%A8%8B%E5%88%9B%E5%BB%BA%E5%AE%8C%E6%AF%95%E4%BB%A5%E5%90%8E%E8%83%BD%E5%A4%9F%E4%BB%A5%E4%B8%80%E4%B8%AA%E7%9B%B8%E5%AF%B9%E4%B8%80%E8%87%B4%E7%9A%84%E6%97%B6%E9%97%B4%E7%82%B9%E5%90%8C%E6%97%B6%E6%89%A7%E8%A1%8C%E7%BA%BF%E7%A8%8B%E4%BB%A3%E7%A0%81%0A
         Coun
@@ -677,16 +677,32 @@
 Count);%0A
+        // %E5%88%9B%E5%BB%BA%E7%BA%BF%E7%A8%8B%0A
         
@@ -814,32 +814,50 @@
 rt();%0A        %7D%0A
+        // %E5%BC%80%E5%A7%8B%E6%89%A7%E8%A1%8C%E7%B4%AF%E5%8A%A0%0A
         startLat
@@ -864,32 +864,52 @@
 ch.countDown();%0A
+        // %E7%AD%89%E5%BE%85%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%0A
         waitLatc
@@ -1021,32 +1021,95 @@
 afe counter:%7B%7D%22,
+ counter.getSyncCount());%0A        log.info(%22atomic counter:%7B%7D%22,
  counter.getAtom
@@ -1183,16 +1183,43 @@
  count;%0A
+    private int syncCount;%0A
     priv
@@ -1294,16 +1294,39 @@
 nt = 0;%0A
+        syncCount = 0;%0A
         
@@ -1470,33 +1470,37 @@
 unt() %7B%0A        
-c
+syncC
 ount++;%0A    %7D%0A%0A 
@@ -1840,24 +1840,86 @@
       try %7B%0A
+            // %E7%BA%BF%E7%A8%8B%E9%BB%98%E8%AE%A4%E6%98%AF%E9%98%BB%E5%A1%9E%E5%9C%A8%E6%AD%A4%E5%A4%84%E7%9A%84,%E4%B8%BB%E7%BA%BF%E7%A8%8B%E8%B0%83%E7%94%A8startLatch.countDown()%E5%8D%B3%E8%A7%A3%E9%99%A4%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%0A
             
@@ -1981,32 +1981,32 @@
 P_TIMES; i++) %7B%0A
-
                 
@@ -2021,32 +2021,69 @@
 notSafeCount();%0A
+                counter.safeCount();%0A
                 

add atomic example