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


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

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

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

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

  • 相关阅读:
    【转】svn冲突问题详解 SVN版本冲突解决详解
    【转】Mysql解决The total number of locks exceeds the lock table size错误
    【转】iOS中修改AVPlayer的请求头信息
    【转】AJAX请求和普通HTTP请求区别
    【转】怎么给javascript + div编辑框光标位置插入表情文字等?
    【转】iOS开发笔记--识别单击还是双击
    【转】Android hdpi ldpi mdpi xhdpi xxhdpi适配详解
    87. Scramble String
    86. Partition List
    85. Maximal Rectangle
  • 原文地址:https://www.cnblogs.com/bangiao/p/11703277.html
Copyright © 2020-2023  润新知