文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

# 深入理解高并发编程(二)

2023-09-26 12:29

关注

深入理解高并发编程(二)

文章目录

synchronized

作用

使用方法

示例代码

public class CreateThreadByRunnableTest {    private static final Logger logger = LoggerFactory.getLogger(CreateThreadByRunnableTest.class);    private static final int TICKET_NUM = 11;        @Test    public void test() throws InterruptedException {        BuyTicketsRunnable buyTicketTask = new BuyTicketsRunnable(TICKET_NUM);        int threadNum = 20;        for (int i = 0; i < threadNum; i++) {            Thread thread = new Thread(buyTicketTask);            thread.start();            if (Thread.holdsLock(Thread.currentThread())) {                logger.info("当前线程持有对象监视器!");            }        }        Thread.sleep(10000);    }    private class BuyTicketsRunnable implements Runnable {        private final Logger logger = LoggerFactory.getLogger(BuyTicketsRunnable.class);        private int ticketNum;        public BuyTicketsRunnable(int aTicketNum) {            this.ticketNum = aTicketNum;        }        @Override        public void run() {            synchronized (this) {                if (ticketNum > 0) {                    ticketNum--;                    logger.info("Thread {} 买到一张票 还剩:{} 张票", Thread.currentThread().getId(), ticketNum);                } else {                    logger.info("Thread {} 没有抢到票 还剩:{} 张票", Thread.currentThread().getId(), ticketNum);                }            }        }    }}

ReentrantLock

概述

示例代码
@Testpublic void test2() throws InterruptedException {    TicketTask ticketTask = new TicketTask();    new Thread(ticketTask, "1号窗口").start();    new Thread(ticketTask, "2号窗口").start();    new Thread(ticketTask, "3号窗口").start();    Thread.sleep(10000);}private class TicketTask implements Runnable {    private final Logger logger = LoggerFactory.getLogger(TicketTask.class);    private int tickets = 100;    private final Lock lock = new ReentrantLock(false);    @Override    public void run() {        while (true) {            // 上Lock锁            lock.lock();            try {                if (tickets > 0) {                    --tickets;                    logger.info("{} ======完成售票,余票为{}", Thread.currentThread().getName(), tickets);                } else {                    logger.info("{} ======余票为{}", Thread.currentThread().getName(), tickets);                    break;                }            } catch (Exception e) {                logger.error(e.getMessage(), e);            } finally {                // 释放 Lock 锁避免发生死锁                lock.unlock();            }        }    }}
ReentrantLock中的方法

ReentrantReadWriteLock

介绍
特点
示例代码
public class ReadWriteLockTest {    @Test    public void test() throws InterruptedException {        // 创建读写锁        ReadWriteLock lock = new ReentrantReadWriteLock();        // 读锁        Lock readLock = lock.readLock();        // 写锁        Lock writeLock = lock.writeLock();        Map<String, Object> map = new HashMap<>();        for (int i = 10; i > 0; i--) {            String key = String.valueOf(System.currentTimeMillis());            WriteTask writeTask = new WriteTask(writeLock, map, key);            ReadTask readTask = new ReadTask(readLock, map, key);            ThreadPoolUtils.executor(writeTask);            ThreadPoolUtils.executor(readTask);        }        Thread.sleep(10000);    }        private class ReadTask implements Runnable {        private final Logger logger = LoggerFactory.getLogger(ReadTask.class);        private Lock readLock;        private Map<String, Object> map;        private String key;        private ReadTask(Lock readLock, Map<String, Object> map, String key) {            this.readLock = readLock;            this.map = map;            this.key = key;        }        @Override        public void run() {            readLock.lock();            try {                if (Objects.nonNull(map)) {                    Object object = map.get(key);                    logger.info("ReadTask read value:{}", object);                }            } catch (Exception e) {                logger.error(e.getMessage(), e);            } finally {                // 释放锁                readLock.unlock();            }        }    }        private class WriteTask implements Runnable {        private final Logger logger = LoggerFactory.getLogger(WriteTask.class);        private Lock writeLock;        private Map<String, Object> map;        private String key;        private WriteTask(Lock writeLock, Map<String, Object> map, String key) {            this.writeLock = writeLock;            this.map = map;            this.key = key;        }        @Override        public void run() {            writeLock.lock();            try {                if (Objects.isNull(map)) {                    map = new HashMap<>();                }                long l = System.currentTimeMillis();                map.put(key, l);                logger.info("WriteTask write value:{}", l);            } catch (Exception e) {                logger.error(e.getMessage(), e);            } finally {                // 释放锁                writeLock.unlock();            }        }    }}

StampedLock

示例代码
public class StampedLockTest {    private static final Logger logger = LoggerFactory.getLogger(StampedLockTest.class);    @Test    public void test1() throws InterruptedException {        StampedLock lock = new StampedLock();        List<String> list = new ArrayList<>();        ReadTask readTask = new ReadTask(lock, list);        WriteTask writeTask = new WriteTask(lock, list);        for (int i = 0; i < 20; i++) {            new Thread(readTask).start();            new Thread(writeTask).start();        }        Thread.sleep(10000);    }        private class ReadTask implements Runnable {        private StampedLock lock;        List<String> list;        public ReadTask(StampedLock lock, List<String> list) {            this.lock = lock;            this.list = list;        }        @Override        public void run() {            // 尝试获取乐观读锁            long stamp = lock.tryOptimisticRead();            // 检查乐观读锁是否有效            if (!lock.validate(stamp)) {                // 获取悲观读锁                stamp = lock.readLock();                try {                    logger.info("读取到值:{}", list.toString());                } finally {                    // 释放读锁                    lock.unlockRead(stamp);                }            }        }    }    private class WriteTask implements Runnable {        private StampedLock lock;        List<String> list;        public WriteTask(StampedLock lock, List<String> list) {            this.lock = lock;            this.list = list;        }        @Override        public void run() {            // 获取写锁            long stamp = lock.writeLock();            try {                // 修改共享资源                list.add(UUID.randomUUID().toString());                logger.info("写入值后 list 的大小:{}", list.size());            } finally {                // 释放写锁                lock.unlockWrite(stamp);            }        }    }}

wait() 和 notify()

示例代码

public class WaitNotifyTest {    private static final Logger logger = LoggerFactory.getLogger(WaitNotifyTest.class);    @Test    public void test1() throws InterruptedException {        for (int i = 0; i < 10; i++) {            Message message = new Message();            int finalI = i;            ThreadPoolUtils.executor(new Thread(() -> {                logger.info(message.getMessage());            }));            ThreadPoolUtils.executor(new Thread(() -> {                message.setMessage("消息" + finalI);            }));        }        Thread.sleep(10000);    }    private class Message {        private String content;        private boolean isMessageReady;        public synchronized void setMessage(String content) {            while (isMessageReady) {                try {                    // 等待,直到消息被消费                    logger.info("消息没有被消费,等待被消费:{}", content);                    wait();                } catch (InterruptedException e) {                    Thread.currentThread().interrupt();                }            }            this.content = content;            isMessageReady = true;            // 唤醒等待的线程            notify();        }        public synchronized String getMessage() {            while (!isMessageReady) {                try {                    // 等待,直到消息被设置                    logger.info("消息为空等待有消息", content);                    wait();                } catch (InterruptedException e) {                    Thread.currentThread().interrupt();                }            }            isMessageReady = false;            // 唤醒等待的线程            notify();            return content;        }    }}

并发编程——可见性问题

单核CPU

多核CPU存在可见性问题

总结

并发编程——原子性问题

解决方法

Java提供了一些机制来解决原子性问题,包括以下几种方式:

需要注意的是,并发编程中的原子性问题不仅仅限于对共享变量的操作,还可能涉及到多个操作的组合,这时候就需要考虑使用更高级的并发编程技术,如原子操作的组合、事务等。

并发编程——有序性问题

指令重排序

编译器重排序
处理器重排序

现代处理器为了提高指令的执行效率,可能会对指令进行乱序执行或重排序。处理器重排序是在单线程环境下的,同样不会影响单线程程序的执行结果。

解决方法(同步机制)

使用 volatile
private static volatile ThreadPoolExecutor threadPool;
synchronized
public class LazySingleton {    private static final Logger logger = LoggerFactory.getLogger(LazySingleton.class);        private static volatile LazySingleton lazySingleton;        private LazySingleton() {    }        public static synchronized LazySingleton getInstance() {        if (null == lazySingleton) {            logger.info("懒汉式单例创建对象!");            lazySingleton = new LazySingleton();        }        return lazySingleton;    }}
使用显式的锁
private static Lock LOCK = new ReentrantLock();@Testpublic void test2() {    for (int i = 0; i < 1000; i++) {        new Thread(() -> {            LOCK.lock();            try {                String dateString = simpleDateFormat.format(new Date());                Date parse = simpleDateFormat.parse(dateString);                logger.info(simpleDateFormat.format(parse));            } catch (Exception e) {                logger.error(e.getMessage(), e);            } finally {                LOCK.unlock();            }        }).start();    }}
使用并发工具类
public class SemaphoreTest {    private static final Logger logger = LoggerFactory.getLogger(SemaphoreTest.class);    private static final Semaphore semaphore1 = new Semaphore(0);    private static final Semaphore semaphore2 = new Semaphore(0);    private class One extends Thread {        @Override        public void run() {            logger.info("=====》One线程执行完成...");            semaphore1.release();        }    }    private class Two extends Thread {        @Override        public void run() {            try {                semaphore1.acquire();                logger.info("=====》Two线程执行完成...");                semaphore2.release();            } catch (InterruptedException e) {                logger.error(e.getMessage(), e);            }        }    }    private class Three extends Thread {        @Override        public void run() {            try {                semaphore2.acquire();                logger.info("======》Three线程执行完成...");                semaphore2.release();            } catch (InterruptedException e) {                logger.error(e.getMessage(), e);            }        }    }    @Test    public void test1() throws InterruptedException {        Thread one = new One();        one.start();        Thread two = new Two();        two.start();        Thread three = new Three();        three.start();        Thread.sleep(5000);        logger.info("=====>三个子线程结束...");    }}

Java内存屏障

作用

来源地址:https://blog.csdn.net/qq_37248504/article/details/133294447

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯