• 使用无锁完成多线程模拟售票, 理解无锁是啥?


    实现的模拟多线程实现售票是每个学习多线程的初学者必须要学会掌握的知识点, 既然掌握的它, 我们自然要举一反三

    So~, 无锁版出现了

    What无锁?

    假如两个线程同时修改一个变量的场景下

    我们需要三个值, 预期值(线程副本变量中的值), 主存值(从主存变量中的值), 新值(我们要设置的值)

    如果 预期值 不等于 主存值 则忽略 新值 写入  =========> 这句话是一个原子操作, 是不可分割的(就是内存屏障), 在执行这个过程中, 是不会失去时间片的

    如果 预期值 等于 主存值 则  新值 写入  =========> 这句话是一个原子操作, 是不可分割的(就是内存屏障), 在执行这个过程中, 是不会失去时间片的

    直接上代码就能理解了, 这是多线程模拟售票的案例, 里面有无锁和加锁的案例

    package com.zhazha.juc;
    
    import org.junit.Test;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @author zhazha
     * @version 1.0.0
     * @date 2019/10/19 9:39
     * @msg
     **/
    public class TestTicketAtomicLock {
    
        @Test
        public void test01() throws Exception {
            CountDownLatch latch = new CountDownLatch(3);
            TicketAtomic ticket = new TicketAtomic(latch);
            for (int i = 0; i < 3; i++) {
                new Thread(ticket).start();
            }
            latch.await();
        }
    
        @Test
        public void test() throws Exception {
            CountDownLatch latch = new CountDownLatch(3);
            TicketNonAtomic ticket = new TicketNonAtomic(latch);
            for (int i = 0; i < 3; i++) {
                new Thread(ticket).start();
            }
            latch.await();
        }
    
    }
    
    
    class TicketAtomic implements Runnable {
    
        private AtomicInteger ticket = new AtomicInteger(100);
        private CountDownLatch latch;
    
        public TicketAtomic(CountDownLatch latch) {
            this.latch = latch;
        }
    
        @Override
        public void run() {
            while (true) {
                try {
                    int temp = ticket.get();
                    if (temp > 0) {
                        // TimeUnit.MILLISECONDS.sleep(100);
                        if (ticket.compareAndSet(temp, ticket.get() - 1)) {
                            System.out.println(Thread.currentThread().getName() + " 	成功售票, 余票为: " + ticket.get());
                        }
                    }
                    else {
                        break;
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
            latch.countDown();
        }
    }
    
    
    class TicketNonAtomic implements Runnable {
    
        private Integer ticket = 100;
        private Lock lock = new ReentrantLock();
        private CountDownLatch latch;
    
        public TicketNonAtomic(CountDownLatch latch) {
            this.latch = latch;
        }
    
        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    if (ticket > 0) {
                        // TimeUnit.MILLISECONDS.sleep(100);
                        System.out.println(Thread.currentThread().getName() + " 	成功售票, 余票为: " + --ticket);
                    }
                    else {
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
            latch.countDown();
        }
    }
    

    上面无锁代码中, 最重要的是这句话

    if (ticket.compareAndSet(temp, ticket.get() - 1)) {

    内部代码

     再进去就是用c++实现的无锁

     这步是原子性操作的, 整个过程

    如果 预期值 不等于 主存值 则忽略 新值 写入 等于 主存值 则 写入

  • 相关阅读:
    linux环境下Redis主从复制和集群环境搭建
    2017年秋季学期软件工程第二次作业
    《人月神话》读后感
    功能需求描述
    初学Windows应用程序开发遇到的几个专业名词解释
    2017年秋季学期软件工程第一次作业(曹洪茹)
    第二次四则运算完善
    《人月神话》读后感
    软件工程课上随笔-规约
    2017软件工程第三次作业
  • 原文地址:https://www.cnblogs.com/bangiao/p/11703277.html
Copyright © 2020-2023  润新知