线程原子性例子

先写一个demo的例子

package wg.fnd.test;

/**
 * @author [email protected]
 * @create 2019-03-14 10:56
 */
public class Demo {

    int i = 0;

    public void incr(){
        i++;
    }

    public static void main(String[] args) {
        Demo demo = new Demo();

        for (int j = 0;j<2;j++) {
            new Thread(() -> { // 创建两个线程
                for (int k=0;k<10000;k++) { // 每个线程跑10000次
                    demo.incr();
                }
            }
            ).start();
        }
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(demo.i);
    }
}

这个例子中执行的结果可能是20000,或者小于20000的值,因为变量i在这是不具备原子性的,加上线程执行顺序的问题,所以出现这样的结果。
改变上边的例子,用jdk的Atomic来创建一个变量

package wg.fnd.test;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author [email protected]
 * @create 2019-03-14 10:56
 */
public class AtomicDemo {

//    int i = 0;

    AtomicInteger i = new AtomicInteger(0);

    public void incr(){
//        i++;
        i.incrementAndGet();
    }

    public static void main(String[] args) {
        AtomicDemo demo = new AtomicDemo();

        for (int j = 0;j<2;j++) {
            new Thread(() -> { // 创建两个线程
                for (int k=0;k<10000;k++) { // 每个线程跑10000次
                    demo.incr();
                }
            }
            ).start();
        }
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(demo.i);
    }
}

这个例子中执行的结果一定为20000
用加锁的方式改变demo

package wg.fnd.test;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author [email protected]
 * @create 2019-03-14 10:56
 */
public class LockDemo {

    int i = 0;
    Lock lock = new ReentrantLock();

    public void incr(){
        lock.lock();
        try {
            i++;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        LockDemo demo = new LockDemo();

        for (int j = 0;j<2;j++) {
            new Thread(() -> { // 创建两个线程
                for (int k=0;k<10000;k++) { // 每个线程跑10000次
                    demo.incr();
                }
            }
            ).start();
        }

        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(demo.i);
    }
}

这个例子的执行结果一定为20000

我们来自己创建一个锁,实现jdk中的Lock

package wg.fnd.test;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;

/**
 * @author [email protected]
 * @create 2019-03-14 11:44
 */
public class MyLock implements Lock {

    AtomicReference owner = new AtomicReference<>(); // atomic类具有原子性
    public LinkedBlockingDeque waiter = new LinkedBlockingDeque<>(); // 等待列表

    @Override
    public void lock() {
        // 多线程,有可能成功,也有可能失败,(一直抢)不能只抢一次
        // 进行比较和交换
        while (!owner.compareAndSet(null, Thread.currentThread())) {
            waiter.add(Thread.currentThread()); // 抢不到就等,把当前线程放入等待列表
            LockSupport.park(); // 让线程等待
            //
            waiter.remove(Thread.currentThread()); //  如果能执行到这里,说明唤醒了线程,那么久移除当前线程
        }
    }

    @Override
    public void unlock() {
        // 判断是否有线程,如果有就释放,没有就不管
        if (owner.compareAndSet(Thread.currentThread(), null)) {
            // 通知那些等待列表的线程,唤醒
            Object[] objects = waiter.toArray(); //数组化
            for (Object object : objects) { // 遍历,拿出所有等待的线程
                Thread next = (Thread) object;
                LockSupport.unpark(next); // 唤醒线程
            }
        }
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

你可能感兴趣的:(java基础)