多线程编程:一个指令重排序引发的chaos
先贴出正确的代码:
package com.xiaobai.thread.main; import lombok.extern.slf4j.Slf4j; @Slf4j
public class ThreadMain { private volatile static int ticket; private static class RunningTask implements Runnable{ public RunningTask(boolean proOrSell) {
this.proOrSell = proOrSell;
} private boolean proOrSell = true;//如果为静态,会被实例共享 public void run() {
while (true) {//只同步需要同步的代码,while(true)不能放在同步里面!!否则除非线程自己wait(),永远不会轮到其他线程!!
synchronized (RunningTask.class) {
proOrSell();
}
}
} private void proOrSell() {
if(proOrSell) {
ticket++;
log.info("Tickets/Pro:" + ticket);
RunningTask.class.notifyAll();
if(ticket >= 1000) {
try {
System.out.println("--------------------------------------------------------------------------------------------------------------------------------------->Pro Wait!!!!!");
RunningTask.class.wait();//持有锁的本线程等待
} catch (InterruptedException e) { }
}
}else {
System.out.println(Thread.currentThread().getName() + " take control!");
if(ticket <= 100) {
try {
System.out.println(Thread.currentThread().getName() + " <=100!");
System.out.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!");
RunningTask.class.wait();
} catch (InterruptedException e) { }
}else {
ticket--;
log.info("Tickets------->Sell:" + ticket);
System.out.println(Thread.currentThread().getName() + " decrease tickets!");
if(ticket <= 500) {
RunningTask.class.notifyAll();
}
}
}
}
} private static void proOrSell() {
Runnable task1 = new RunningTask(true);
Runnable task2 = new RunningTask(false);
Thread thread1 = new Thread(task1);
Thread thread2 = new Thread(task2);
Thread thread3 = new Thread(task2);
Thread thread4 = new Thread(task2);
thread1.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) { }
thread2.start();
thread3.start();
thread4.start();
} public static void main(String[] args) {
proOrSell();
while (ticket <= 0) {
System.out.println("------------------------------------------------------->Ticket System Broken!!!!!!");
System.exit(0);
}
} }
代码简单说明:
1.多线程生产者-消费者程序,一个生产者,3个消费者
2.同步共享变量操作代码,同一把锁(内部嵌套类的字节码对象)
3.注意while(true)要在同步代码外面,否则没有意义!
4.改造的等待-唤醒机制,控制票数在一个下限(100)和一个上限(1000)
正确代码运行结果摘录:
1)
Thread-1 take control!
2018-12-09 21:14:11.357 [Thread-1] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:105
Thread-1 decrease tickets!
Thread-1 take control!
2018-12-09 21:14:11.357 [Thread-1] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:104
Thread-1 decrease tickets!
Thread-1 take control!
2018-12-09 21:14:11.357 [Thread-1] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:103
Thread-1 decrease tickets!
Thread-1 take control!
2018-12-09 21:14:11.357 [Thread-1] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:102
Thread-1 decrease tickets!
Thread-1 take control!
2018-12-09 21:14:11.357 [Thread-1] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:101
Thread-1 decrease tickets!
Thread-1 take control!
2018-12-09 21:14:11.357 [Thread-1] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:100
Thread-1 decrease tickets!
Thread-1 take control!
Thread-1 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
Thread-3 take control!
Thread-3 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
2018-12-09 21:14:11.357 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:101
2018-12-09 21:14:11.357 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:102
2018-12-09 21:14:11.357 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:103
2018-12-09 21:14:11.357 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:104
2)
Thread-2 take control!
2018-12-09 21:14:11.375 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:107
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.375 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:106
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.375 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:105
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.375 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:104
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.375 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:103
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.375 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:102
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.375 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:101
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.375 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:100
Thread-2 decrease tickets!
Thread-2 take control!
Thread-2 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
Thread-3 take control!
Thread-3 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
Thread-1 take control!
Thread-1 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
2018-12-09 21:14:11.376 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:101
2018-12-09 21:14:11.376 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:102
2018-12-09 21:14:11.376 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:103
2018-12-09 21:14:11.376 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:104
2018-12-09 21:14:11.376 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:105
3)
Thread-2 take control!
2018-12-09 21:14:11.395 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:104
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.395 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:103
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.395 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:102
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.395 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:101
Thread-2 decrease tickets!
Thread-2 take control!
2018-12-09 21:14:11.395 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:100
Thread-2 decrease tickets!
Thread-2 take control!
Thread-2 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
Thread-3 take control!
Thread-3 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
Thread-1 take control!
Thread-1 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
2018-12-09 21:14:11.395 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:101
2018-12-09 21:14:11.395 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:102
2018-12-09 21:14:11.395 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:103
2018-12-09 21:14:11.395 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:104
说明:当票数达到下限100时,三个消费者先后侦测到并在同一个监视器上阻塞等待,由生产者继续屯票,并唤醒消费者继续消费。生产者侦测票数达到1000时暂停生产,阻塞等待。
错误的程序:将else中嵌套的else中的内容拿到外面,去掉嵌套else.也就是说,无论上面的if条件是否满足,都执行现在在嵌套else中的全部内容。
错误程序出现的运行现象:
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:113
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:112
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:111
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:110
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:109
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:108
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:107
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:106
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:105
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:104
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:103
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:102
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:101
Thread-3 decrease tickets!
Thread-3 take control!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:100
Thread-3 decrease tickets!
Thread-3 take control!
Thread-3 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
2018-12-09 20:53:18.891 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:99
Thread-2 decrease tickets!
Thread-2 take control!
Thread-2 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
2018-12-09 20:53:18.891 [Thread-1] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:98
Thread-1 decrease tickets!
Thread-1 take control!
Thread-1 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
2018-12-09 20:53:18.891 [Thread-2] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:97
Thread-2 decrease tickets!
Thread-2 take control!
Thread-2 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
2018-12-09 20:53:18.891 [Thread-3] INFO com.xiaobai.thread.main.ThreadMain -
Tickets------->Sell:96
Thread-3 decrease tickets!
Thread-3 take control!
Thread-3 <=100!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==>Sell Wait!!!!
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:97
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:98
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:99
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:100
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:101
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:102
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:103
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:104
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:105
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:106
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:107
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:108
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:109
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:110
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:111
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:112
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:113
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:114
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:115
2018-12-09 20:53:18.891 [Thread-0] INFO com.xiaobai.thread.main.ThreadMain -
Tickets/Pro:116
分析:通过不同程序段打印和线程名打印可以清晰看到,消费者程序段中发生了指令重排序。if段后面的程序被挪到最前面执行,造成<=100也消费的情况。程序段中一致的线程名和上下文没有不同线程名交叉出现的情况说明同步锁正确且生效,是线程内顺序程序段的指令重排序造成了混乱。将if下面的程序段放在嵌套的else中后,程序执行正常,不再出现<=100消费的情况。生产者这边也没有溢出1000的情况发生。
总结:多线程程序,在注意共享变量操作需要同步需要同步的代码的同时,还需要注意线程内指令重排序造成多线程环境出现混乱的情况,这种情况同样会造成类似非线程安全的情况,但并非线程安全问题,而是同一个线程中的顺序混乱被带到多线程操作中,造成了混乱和不安全。
多线程编程:一个指令重排序引发的chaos的更多相关文章
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- 【java多线程系列】java内存模型与指令重排序
在多线程编程中,需要处理两个最核心的问题,线程之间如何通信及线程之间如何同步,线程之间通信指的是线程之间通过何种机制交换信息,同步指的是如何控制不同线程之间操作发生的相对顺序.很多读者可能会说这还不简 ...
- Java并发编程-线程可见性&线程封闭&指令重排序
一.指令重排序 例子如下: public class Visibility1 { public static boolean ready; public static int number; } pu ...
- 内存可见性,指令重排序,JIT。。。。。。从一个知乎问题谈起
在知乎上看到一个问题<java中volatile关键字的疑惑?>,引起了我的兴趣 问题是这样的: package com.cc.test.volatileTest; public clas ...
- JVM并发机制的探讨——内存模型、内存可见性和指令重排序
并发本来就是个有意思的问题,尤其是现在又流行这么一句话:“高帅富加机器,穷矮搓搞优化”. 从这句话可以看到,无论是高帅富还是穷矮搓都需要深入理解并发编程,高帅富加多了机器,需要协调多台机器或者多个CP ...
- java指令重排序的问题
转载自于:http://my.oschina.net/004/blog/222069?fromerr=ER2mp62C 指令重排序是个比较复杂.觉得有些不可思议的问题,同样是先以例子开头(建议大家跑下 ...
- 不得不提的volatile及指令重排序(happen-before)
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- 使用 volatile 关键字保证变量可见性和禁止指令重排序
volatile 概述 volatile 是 Java 提供的一种轻量级的同步机制.相比于传统的 synchronize,虽然 volatile 能实现的同步性要差一些,但开销更低,因为它不会引起频繁 ...
随机推荐
- hdu3037 lucas
题意 : 给了n课不同的树,要求将 0,1,2,3,4,5,...m个松果,分别放在n棵树上的方案数有多少, 我们这样考虑, 如果将m个相同的松果 放入n棵树中 , 转化一下,我们让每个点至少放1个 ...
- vue路由6:导航钩子
<div id="app"> <div> <router-link to="/">首页</router-link> ...
- Step4:SQL Server 跨网段(跨机房)复制
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 解决方案(Solution) 搭建过程(Process) 注意事项(Attention) 参考 ...
- CAT Caterpillar ET Diagnostic Adapter has a powerful function
As a excellent Professional Diagnostic Tools products, CAT Caterpillar ET Diagnostic Adapter has a p ...
- 前端框架VUE----nodejs中npm的使用
NPM是什么? 简单的说,npm就是JavaScript的包管理工具.类似Java语法中的maven,gradle,python中的pip. 安装 傻瓜式的安装. 第一步:打开https://node ...
- 前端框架VUE----指令
一.什么是VUE? 它是构建用户界面的JavaScript框架(让它自动生成js,css,html等) 二.怎么使用VUE? 1.引入vue.js 2.展示HTML <div id=" ...
- 解决keepalived脑裂问题
检测思路:正常情况下keepalived的VIP地址是在主节点上的,如果在从节点发现了VIP,就设置报警信息 脚本如下: #!/bin/bash # 检查脑裂的脚本,在备节点上进行部署 LB01_VI ...
- 已知宽高和未知宽高的div块的水平垂直居中
//已知宽高的情况 .div1_container{ border:1px solid #00ee00; height:300px; position:relative; } ...
- 双屏互动h5
情侣H5:https://www.25xt.com/allcode/10837.html 双屏互动:https://www.digitaling.com/articles/18180.html
- Golang并发编程有缓冲通道和无缓冲通道(channel)
无缓冲通道 是指在接收前没有能力保存任何值得通道.这种类型的通道要求发送goroutine和接收goroutine同时准备好,才能完成发送和接收操作.如果两个goroutine没有同时准备好,通道会导 ...