zoukankan      html  css  js  c++  java
  • 使用无锁完成多线程模拟售票, 理解无锁是啥?

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

    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++实现的无锁

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

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

  • 相关阅读:
    机器学习(深度学习)
    机器学习(六)
    机器学习一-三
    Leetcode 90. 子集 II dfs
    Leetcode 83. 删除排序链表中的重复元素 链表操作
    《算法竞赛进阶指南》 第二章 Acwing 139. 回文子串的最大长度
    LeetCode 80. 删除有序数组中的重复项 II 双指针
    LeetCode 86 分割链表
    《算法竞赛进阶指南》 第二章 Acwing 138. 兔子与兔子 哈希
    《算法竞赛进阶指南》 第二章 Acwing 137. 雪花雪花雪花 哈希
  • 原文地址:https://www.cnblogs.com/bangiao/p/11703277.html
Copyright © 2011-2022 走看看