viscent / javamtia Goto Github PK
View Code? Open in Web Editor NEW《Java多线程编程实战指南(核心篇)》的配套源码
Home Page: https://book.douban.com/subject/27034721/
License: Other
《Java多线程编程实战指南(核心篇)》的配套源码
Home Page: https://book.douban.com/subject/27034721/
License: Other
ch4/case02/RecordProcessor.java 第 136 行代码块是什么意思?recordParts.length 难道恒等于 11 吗?
黄老师,书上每章后面的思维导图能发出来吗?
问题描述:
1、测试结果中有两个线程拿到一样的值
2、还有一种情况是线程获取的值顺序不对
count的变量值在增加的时候使用了锁,也就是同时只有一个线程对count变量做修改,读取变量增量了volatile保障读取到最新的值,但是实际反复测试确不是这样,麻烦老师解惑下谢谢
测试的代码如下
package io.github.viscent.mtia.ch3.case03;
import io.github.viscent.mtia.ch3.Counter;
import io.github.viscent.mtia.util.Debug;
public class ThreadTest {
public static void main(String[] args) {
Counter counter = new Counter();
Thread thread =new Thread(){
@Override
public void run() {
for(int i=0;i<50;i++){
counter.increment();
Debug.info(counter.vaule()+"");
}
}
};
Thread thread1 =new Thread(){
@Override
public void run() {
for(int i=0;i<50;i++){
counter.increment();
Debug.info(counter.vaule()+"");
}
}
};
thread.start();
thread1.start();
}
}
问题1 的测试结果
[2020-07-08 10:16:44.446][INFO][Thread-0]:2
[2020-07-08 10:16:44.446][INFO][Thread-1]:2
[2020-07-08 10:16:44.451][INFO][Thread-0]:3
[2020-07-08 10:16:44.451][INFO][Thread-1]:4
[2020-07-08 10:16:44.451][INFO][Thread-0]:5
[2020-07-08 10:16:44.451][INFO][Thread-1]:6
[2020-07-08 10:16:44.451][INFO][Thread-0]:7
[2020-07-08 10:16:44.451][INFO][Thread-1]:8
[2020-07-08 10:16:44.451][INFO][Thread-0]:9
[2020-07-08 10:16:44.451][INFO][Thread-1]:10
[2020-07-08 10:16:44.451][INFO][Thread-0]:11
[2020-07-08 10:16:44.451][INFO][Thread-1]:12
[2020-07-08 10:16:44.452][INFO][Thread-0]:13
[2020-07-08 10:16:44.452][INFO][Thread-0]:15
[2020-07-08 10:16:44.452][INFO][Thread-1]:14
[2020-07-08 10:16:44.452][INFO][Thread-0]:16
[2020-07-08 10:16:44.452][INFO][Thread-0]:17
[2020-07-08 10:16:44.452][INFO][Thread-0]:18
[2020-07-08 10:16:44.452][INFO][Thread-0]:19
[2020-07-08 10:16:44.452][INFO][Thread-1]:20
[2020-07-08 10:16:44.452][INFO][Thread-0]:21
[2020-07-08 10:16:44.452][INFO][Thread-1]:22
[2020-07-08 10:16:44.452][INFO][Thread-0]:23
[2020-07-08 10:16:44.453][INFO][Thread-1]:24
[2020-07-08 10:16:44.453][INFO][Thread-0]:25
[2020-07-08 10:16:44.453][INFO][Thread-1]:26
[2020-07-08 10:16:44.453][INFO][Thread-0]:27
[2020-07-08 10:16:44.453][INFO][Thread-1]:28
[2020-07-08 10:16:44.453][INFO][Thread-1]:30
[2020-07-08 10:16:44.453][INFO][Thread-0]:29
[2020-07-08 10:16:44.453][INFO][Thread-1]:31
[2020-07-08 10:16:44.453][INFO][Thread-0]:32
[2020-07-08 10:16:44.453][INFO][Thread-1]:33
[2020-07-08 10:16:44.454][INFO][Thread-0]:34
[2020-07-08 10:16:44.454][INFO][Thread-1]:35
[2020-07-08 10:16:44.454][INFO][Thread-0]:36
[2020-07-08 10:16:44.454][INFO][Thread-1]:37
[2020-07-08 10:16:44.454][INFO][Thread-0]:38
[2020-07-08 10:16:44.454][INFO][Thread-1]:39
[2020-07-08 10:16:44.454][INFO][Thread-0]:40
[2020-07-08 10:16:44.454][INFO][Thread-1]:41
[2020-07-08 10:16:44.454][INFO][Thread-0]:42
[2020-07-08 10:16:44.454][INFO][Thread-1]:43
[2020-07-08 10:16:44.454][INFO][Thread-0]:44
[2020-07-08 10:16:44.454][INFO][Thread-1]:45
[2020-07-08 10:16:44.454][INFO][Thread-0]:46
[2020-07-08 10:16:44.454][INFO][Thread-1]:47
[2020-07-08 10:16:44.455][INFO][Thread-0]:48
[2020-07-08 10:16:44.455][INFO][Thread-1]:49
[2020-07-08 10:16:44.455][INFO][Thread-0]:50
[2020-07-08 10:16:44.455][INFO][Thread-1]:51
[2020-07-08 10:16:44.455][INFO][Thread-0]:52
[2020-07-08 10:16:44.455][INFO][Thread-1]:53
[2020-07-08 10:16:44.455][INFO][Thread-0]:54
[2020-07-08 10:16:44.455][INFO][Thread-1]:55
[2020-07-08 10:16:44.455][INFO][Thread-0]:56
[2020-07-08 10:16:44.455][INFO][Thread-1]:57
[2020-07-08 10:16:44.455][INFO][Thread-0]:58
[2020-07-08 10:16:44.455][INFO][Thread-1]:59
[2020-07-08 10:16:44.455][INFO][Thread-0]:60
[2020-07-08 10:16:44.456][INFO][Thread-1]:61
[2020-07-08 10:16:44.456][INFO][Thread-0]:62
[2020-07-08 10:16:44.456][INFO][Thread-1]:63
[2020-07-08 10:16:44.456][INFO][Thread-0]:64
[2020-07-08 10:16:44.456][INFO][Thread-1]:65
[2020-07-08 10:16:44.456][INFO][Thread-0]:66
[2020-07-08 10:16:44.456][INFO][Thread-1]:67
[2020-07-08 10:16:44.456][INFO][Thread-0]:68
[2020-07-08 10:16:44.456][INFO][Thread-1]:69
[2020-07-08 10:16:44.456][INFO][Thread-0]:70
[2020-07-08 10:16:44.456][INFO][Thread-1]:71
[2020-07-08 10:16:44.456][INFO][Thread-0]:72
[2020-07-08 10:16:44.456][INFO][Thread-1]:73
[2020-07-08 10:16:44.457][INFO][Thread-0]:74
[2020-07-08 10:16:44.457][INFO][Thread-1]:75
[2020-07-08 10:16:44.457][INFO][Thread-0]:76
[2020-07-08 10:16:44.457][INFO][Thread-1]:77
[2020-07-08 10:16:44.457][INFO][Thread-0]:78
[2020-07-08 10:16:44.457][INFO][Thread-1]:79
[2020-07-08 10:16:44.457][INFO][Thread-0]:80
[2020-07-08 10:16:44.457][INFO][Thread-1]:81
[2020-07-08 10:16:44.457][INFO][Thread-0]:82
[2020-07-08 10:16:44.457][INFO][Thread-1]:83
[2020-07-08 10:16:44.457][INFO][Thread-0]:84
[2020-07-08 10:16:44.458][INFO][Thread-1]:85
[2020-07-08 10:16:44.458][INFO][Thread-0]:86
[2020-07-08 10:16:44.458][INFO][Thread-1]:87
[2020-07-08 10:16:44.458][INFO][Thread-0]:88
[2020-07-08 10:16:44.458][INFO][Thread-1]:89
[2020-07-08 10:16:44.458][INFO][Thread-0]:90
[2020-07-08 10:16:44.458][INFO][Thread-1]:91
[2020-07-08 10:16:44.458][INFO][Thread-0]:92
[2020-07-08 10:16:44.458][INFO][Thread-1]:93
[2020-07-08 10:16:44.458][INFO][Thread-0]:94
[2020-07-08 10:16:44.458][INFO][Thread-1]:95
[2020-07-08 10:16:44.458][INFO][Thread-0]:96
[2020-07-08 10:16:44.458][INFO][Thread-1]:97
[2020-07-08 10:16:44.459][INFO][Thread-1]:98
[2020-07-08 10:16:44.459][INFO][Thread-1]:99
[2020-07-08 10:16:44.459][INFO][Thread-1]:100
问题2的测试结果
[2020-07-08 10:36:42.029][INFO][Thread-1]:2
[2020-07-08 10:36:42.029][INFO][Thread-0]:1
[2020-07-08 10:36:42.033][INFO][Thread-1]:3
[2020-07-08 10:36:42.033][INFO][Thread-0]:4
[2020-07-08 10:36:42.033][INFO][Thread-1]:5
[2020-07-08 10:36:42.034][INFO][Thread-1]:7
[2020-07-08 10:36:42.034][INFO][Thread-1]:8
[2020-07-08 10:36:42.035][INFO][Thread-1]:9
[2020-07-08 10:36:42.035][INFO][Thread-1]:10
[2020-07-08 10:36:42.034][INFO][Thread-0]:6
[2020-07-08 10:36:42.035][INFO][Thread-1]:11
[2020-07-08 10:36:42.035][INFO][Thread-1]:13
[2020-07-08 10:36:42.035][INFO][Thread-0]:12
[2020-07-08 10:36:42.035][INFO][Thread-0]:15
[2020-07-08 10:36:42.035][INFO][Thread-0]:16
[2020-07-08 10:36:42.035][INFO][Thread-1]:14
[2020-07-08 10:36:42.035][INFO][Thread-0]:17
[2020-07-08 10:36:42.035][INFO][Thread-1]:18
[2020-07-08 10:36:42.035][INFO][Thread-0]:19
[2020-07-08 10:36:42.035][INFO][Thread-0]:21
[2020-07-08 10:36:42.035][INFO][Thread-0]:22
[2020-07-08 10:36:42.035][INFO][Thread-1]:20
[2020-07-08 10:36:42.035][INFO][Thread-0]:23
[2020-07-08 10:36:42.036][INFO][Thread-0]:25
[2020-07-08 10:36:42.036][INFO][Thread-1]:24
[2020-07-08 10:36:42.036][INFO][Thread-0]:26
[2020-07-08 10:36:42.036][INFO][Thread-1]:27
[2020-07-08 10:36:42.036][INFO][Thread-0]:28
[2020-07-08 10:36:42.036][INFO][Thread-1]:29
[2020-07-08 10:36:42.036][INFO][Thread-0]:30
[2020-07-08 10:36:42.036][INFO][Thread-1]:31
[2020-07-08 10:36:42.036][INFO][Thread-0]:32
[2020-07-08 10:36:42.036][INFO][Thread-1]:33
[2020-07-08 10:36:42.037][INFO][Thread-0]:34
[2020-07-08 10:36:42.037][INFO][Thread-1]:35
[2020-07-08 10:36:42.037][INFO][Thread-0]:36
[2020-07-08 10:36:42.037][INFO][Thread-1]:37
[2020-07-08 10:36:42.037][INFO][Thread-0]:38
[2020-07-08 10:36:42.037][INFO][Thread-1]:39
[2020-07-08 10:36:42.037][INFO][Thread-0]:40
[2020-07-08 10:36:42.037][INFO][Thread-1]:41
[2020-07-08 10:36:42.037][INFO][Thread-0]:42
[2020-07-08 10:36:42.037][INFO][Thread-1]:43
[2020-07-08 10:36:42.037][INFO][Thread-0]:44
[2020-07-08 10:36:42.038][INFO][Thread-1]:45
[2020-07-08 10:36:42.038][INFO][Thread-0]:46
[2020-07-08 10:36:42.038][INFO][Thread-1]:47
[2020-07-08 10:36:42.038][INFO][Thread-0]:48
[2020-07-08 10:36:42.038][INFO][Thread-1]:49
[2020-07-08 10:36:42.038][INFO][Thread-0]:50
[2020-07-08 10:36:42.038][INFO][Thread-1]:51
[2020-07-08 10:36:42.038][INFO][Thread-1]:53
[2020-07-08 10:36:42.038][INFO][Thread-0]:52
[2020-07-08 10:36:42.038][INFO][Thread-1]:54
[2020-07-08 10:36:42.038][INFO][Thread-0]:55
[2020-07-08 10:36:42.038][INFO][Thread-1]:56
[2020-07-08 10:36:42.038][INFO][Thread-0]:57
[2020-07-08 10:36:42.039][INFO][Thread-1]:58
[2020-07-08 10:36:42.039][INFO][Thread-0]:59
[2020-07-08 10:36:42.039][INFO][Thread-1]:60
[2020-07-08 10:36:42.039][INFO][Thread-0]:61
[2020-07-08 10:36:42.039][INFO][Thread-1]:62
[2020-07-08 10:36:42.039][INFO][Thread-0]:63
[2020-07-08 10:36:42.039][INFO][Thread-0]:65
[2020-07-08 10:36:42.040][INFO][Thread-0]:66
[2020-07-08 10:36:42.040][INFO][Thread-0]:67
[2020-07-08 10:36:42.040][INFO][Thread-0]:68
[2020-07-08 10:36:42.040][INFO][Thread-0]:69
[2020-07-08 10:36:42.040][INFO][Thread-0]:70
[2020-07-08 10:36:42.040][INFO][Thread-0]:71
[2020-07-08 10:36:42.040][INFO][Thread-0]:72
[2020-07-08 10:36:42.041][INFO][Thread-0]:73
[2020-07-08 10:36:42.041][INFO][Thread-0]:74
[2020-07-08 10:36:42.041][INFO][Thread-0]:75
[2020-07-08 10:36:42.039][INFO][Thread-1]:64
[2020-07-08 10:36:42.041][INFO][Thread-1]:77
[2020-07-08 10:36:42.042][INFO][Thread-1]:78
[2020-07-08 10:36:42.042][INFO][Thread-1]:79
[2020-07-08 10:36:42.042][INFO][Thread-1]:80
[2020-07-08 10:36:42.041][INFO][Thread-0]:76
[2020-07-08 10:36:42.042][INFO][Thread-1]:81
[2020-07-08 10:36:42.042][INFO][Thread-0]:82
[2020-07-08 10:36:42.042][INFO][Thread-1]:83
[2020-07-08 10:36:42.042][INFO][Thread-0]:84
[2020-07-08 10:36:42.042][INFO][Thread-1]:85
[2020-07-08 10:36:42.043][INFO][Thread-1]:87
[2020-07-08 10:36:42.043][INFO][Thread-1]:88
[2020-07-08 10:36:42.043][INFO][Thread-1]:89
[2020-07-08 10:36:42.042][INFO][Thread-0]:86
[2020-07-08 10:36:42.043][INFO][Thread-1]:90
[2020-07-08 10:36:42.043][INFO][Thread-0]:91
[2020-07-08 10:36:42.043][INFO][Thread-1]:92
[2020-07-08 10:36:42.043][INFO][Thread-0]:93
[2020-07-08 10:36:42.043][INFO][Thread-1]:94
[2020-07-08 10:36:42.043][INFO][Thread-0]:95
[2020-07-08 10:36:42.043][INFO][Thread-1]:96
[2020-07-08 10:36:42.044][INFO][Thread-1]:98
[2020-07-08 10:36:42.044][INFO][Thread-1]:99
[2020-07-08 10:36:42.044][INFO][Thread-1]:100
[2020-07-08 10:36:42.044][INFO][Thread-0]:97
请问黄老师,静态代码块在类加载的时候算原子操作么,如果不是原子操作,那也有可能出现线程不安全吧,那如果在静态代码块中new 了对象,且发生了重排序,是不是也有可能拿到没有初始化完全的引用呢,谢谢!
createStoreFile() 创建 RandomAccessFile 后 为什么又关闭掉 然后再构造函数中又重新创建呢?是为了提前处理异常吗?
按照代码,很难触发线程可见性问题,但是如果改为
public void run() {
while (!ready) {
count++;
}
if (ready) {
System.out.println("---> 结束啦");
}
}
public void cancel() {
ready = true;
System.out.println("cancel..");
}
这样任务就不能停止了,然后-server 加不加都一样。应该是混合编译的问题吧。是不是原代码加了 Tools.randomPause,导致jit失效?
ch4/case02/RecordProsessor.java 104 行是否和 109 行重复
public class FileDownloaderApp {
public static void main(String[] args) {
Thread downloaderThread = null;
for (String url : args) {
// 创建文件下载器线程
downloaderThread = new Thread(new FileDownloader(url)); // URL 该如何传?
// 启动文件下载器线程
downloaderThread.start();
}
}
// 文件下载器
static class FileDownloader implements Runnable {
private final String fileURL;
public FileDownloader(String fileURL) {
this.fileURL = fileURL;
}
@Override
public void run() {
Debug.info("Downloading from " + fileURL);
String fileBaseName = fileURL.substring(fileURL.lastIndexOf('/') + 1);
try {
URL url = new URL(fileURL);
String localFileName = System.getProperty("java.io.tmpdir")
+ "/viscent-"
+ fileBaseName;
Debug.info("Saving to: " + localFileName);
downloadFile(url, new FileOutputStream(
localFileName), 1024);
} catch (Exception e) {
e.printStackTrace();
}
Debug.info("Done downloading from " + fileURL);
// 省略其他代码
}
}
上边两处的共享变量的可见性保障有些疑惑
从您书中下面的章节来看子线程对父线程的共享变量是没法保障可见性的,但是这里并没有什么措施保障可见性
清单 2- 8 线程 启动 与 可见 性
public class ThreadStartVisibility {
// 线程间的共享变量
static int data = 0;
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
// 使当前线程休眠R毫秒(R的值为随机数)
Tools.randomPause(50);
// 读取并打印变量data的值
System.out.println(data);
}
};
// 在子线程thread启动前更新变量data的值
data = 1;// 语句①
thread.start();
// 使当前线程休眠R毫秒(R的值为随机数)
Tools.randomPause(50);
// 在子线程thread启动后更新变量data的值
data = 2;// 语句②
}
}
如果 我们 把 上述 程序 中的 语句 ② 注释 掉, 则 由于 main 线程 在 启动 其 子 线程 thread 之前 将 共享 变量 data 的 值 更新 为 1( 见 语句 ①), 因此 子 线程 thread 所 读取 到 的 共享 变量 data 的 值 一 定为 1。 这是 由于 父 线程 在 子 线程 启动 前 对 共享 变量 的 更新 对子 线程 的 可见 性 是有 保证 的; 如果 我们 没有 将 语句 ② 注释 掉, 那么 由于 父 线程 在 子 线程 启动 之后 对 共享 变量 的 更新 对子 线程 的 可见 性 是 没有 保证 的, 因此 子 线程 thread 此时 读取 到 的 共享 变量 data 的 值 可 能为 2, 也可能 仍然 为 1。 这就 解释 了 为什么 多次 运行 上述 程序 可以 发现 其 输出 可能 是“ 1”, 也可能 是“ 2”。
黄文海. Java多线程编程实战指南(核心篇) (Java多线程编程实战系列) (Kindle 位置 1142-1147). 电子工业出版社. Kindle 版本.
readme文件里面最好包含一下这个project的目录描述就好了
https://github.com/Viscent/javamtia/blob/06faaaa9610a8b9af2ee0eec551a0365154ef8fa/JavaMultiThreadInAction/src/io/github/viscent/mtia/ch5/ThreadTerminationRegistry.java
有add方法
public synchronized void register(Handler handler) {
handlers.add(handler);
}
但并没有
public synchronized void remove(Handler handler) {
handlers.remove(handler);
}
如果在生产环境中,handlers会越来越大,是否会内存溢出?
private final Set handlers = new HashSet();
能否改为
private final Set handlers = new ConcurrentHashSet();
register 和 remove 方法去掉 synchronized 关键字是否也能达到线程安全,并且效率更高。
比如以下写法:
private final Set handlers = Collections.newSetFromMap(new ConcurrentHashMap<Handler,Boolean>());
public void register(Handler handler) {
handlers.add(handler);
}
public void remove(Handler handler) {
handlers.remove(handler);
}
清单6-5
/**
* 该类是一个错误的Servlet类(非线程安全)
*
* @author Viscent Huang
*/
public class UnsafeServlet extends HttpServlet {
private static final long serialVersionUID = -2772996404655982182L;
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
String strExpiryDate = req.getParameter("expirtyDate");
try {
sdf.parse(strExpiryDate);
} catch (ParseException e) {
e.printStackTrace();
}
// 省略其他代码
}
}
这里的sdf是final,并不会被修改。strExpiryDate是局部变量,也没有问题。
为什么说sdf.parse(strExpiryDate)
调用解析出来的日期可能是一个客户端根本没有提交过的错误日期呢?
这里的nextline变量只有barrierAction. run()执行,也即是说仅有的另外一个访问nextline变量的地方
while (!done) {
soldier = rank[nextLine][index];
// 一排中的士兵必须同时开始射击
startBarrier.await();// 语句③
// 该士兵开始射击
soldier.fire();
// 一排中的士兵必须等待该排中的所有其他士兵射击完毕才能够离开射击点
shiftBarrier.await();// 语句④
}
总是能够读取到最新值,那这里的nextline变量就不需要volatile修饰词了吧
因为您书中这么解释的
设 cyclicBarrier 为 一个 任意 的 CyclicBarrier 实例, 任意 一个 参与 方 在 执行 cyclicBarrier. await() 前所 执行 的 任何 操作 对 barrierAction. run() 而言 是 可见 的、 有序 的。 barrierAction. run() 中 所 执行 的 任何 操作 对 所有 参与 方 在 cyclicBarrier. await() 调用 成功 返回 之后 的 代码 而言 是 可见 的、 有序 的。
黄文海. Java多线程编程实战指南(核心篇) (Java多线程编程实战系列) (Kindle 位置 3851-3854). 电子工业出版社. Kindle 版本.
书籍P394,第三自然段:
StoreStore 屏障可以通过对写缓冲器中的条目进行标记来实现禁止 StoreStore 重排序。
StoreStore 屏障会将写缓冲器中的现有条目做一个标记,以表示这些条目代表的写操作需要先于该屏障之后的写操作被提交。
处理器在执行写操作的时候如果发现写缓冲器中存在被标记的条目,那么即使这个写操作对应的高速缓存条目的状态为E或者M,此时处理器也不直接将写操作的数据写入高速缓存,而是将其写入写缓冲器,从而使得 StoreStore 屏障之前的任何写操作先于该屏障之后的写操作被提交。
请问:
最后一句话,“不直接将写操作的数据写入高速缓存,而是将其写入写缓冲器”是否写错了?既然是左侧store先提交,也就是内存操作作用到主内存(或者高速缓存),那么应该不是写入写缓冲器,而是写入高速缓存吧?这块概念理解有点困难,还盼作者回复,谢谢。
ch4/case02/RecordSet.java 41 行应该 return false 吧
第四章,第二个例子的数据没有共享
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.