👉 通过Demo演示出Java
中并发问题。
可以观察到的实际现象 🙈 比 说说的并发原则 🙊 更直观更可信。
Java
语言标准库支持线程,语言本身(如GC
)以及应用(服务器端The Server side
)中会重度使用多线程。
并发程度设计在分析和实现中,复杂度大大增加。如果不系统理解和充分分析并发逻辑,随意写代码,这样的程序用 『碰巧』 能运行出正确结果 来形容一点都不为过。
# 这里给Demo没有解释和讨论,可以参见并发方面的系统的资料。
你在开发中碰到的并发问题的例子,欢迎提供(提交Issue)和分享(Fork后提交代码)! 😘
Demo类com.oldratlee.fucking.concurrency.NoPublishDemo
。
主线程中设置属性stop
为true
,以控制在main
启动的任务线程退出。
在主线程属性stop
为true
后,但任务线程持续运行,即任务线程中一直没有读到新值。
mvn compile exec:java -Dexec.mainClass=com.oldratlee.fucking.concurrency.NoPublishDemo
long
变量读写不是原子的,会分为2次4字节操作。
Demo类com.oldratlee.fucking.concurrency.InvalidLongDemo
。
主线程修改long
变量,每次写入的long
值的高4字节和低4字节是一样的。在任务线程中读取long
变量。
任务线程中读到了高4字节和低4字节不一样的long
变量,即是无效值(从来没有设置过的值)。
mvn compile exec:java -Dexec.mainClass=com.oldratlee.fucking.concurrency.InvalidLongDemo
这个问题在疫苗:Java HashMap的死循环等多个地方都有讲解。
Demo类com.oldratlee.fucking.concurrency.HashMapHangDemo
,可以复现这个问题。
主线程中开启2个任务线程执行HashMap
的put
操作。主线程做get
操作。
通过没有持续的输出判定主线程Block
,即HashMap
的出现死循环。
mvn compile exec:java -Dexec.mainClass=com.oldratlee.fucking.concurrency.HashMapHangDemo
Demo类com.oldratlee.fucking.concurrency.WrongCounterDemo
。
主线程中开启2个任务线程执行并发递增计数。主线程最终结果检查。
计数值不对。
mvn compile exec:java -Dexec.mainClass=com.oldratlee.fucking.concurrency.WrongCounterDemo
常看到在易变域上的同步代码,并且写的同学会很自然觉得这样是安全和正确的。
# 问题分析见文章链接:在易变域上的同步,对应的英文文章:Synchronization on mutable fields
Demo类com.oldratlee.fucking.concurrency.SynchronizationOnMutableFieldDemo
。
主线程中开启2个任务线程执行addListener
。主线程最终结果检查。
最终Listener
的个数不对。
mvn compile exec:java -Dexec.mainClass=com.oldratlee.fucking.concurrency.SynchronizationOnMutableFieldDemo
# 问题分析见文章链接:对称锁死锁,对应的英文文章:Synchronization on mutable fields
Demo类com.oldratlee.fucking.concurrency.SymmetricLockDeadlockDemo
。
主线程中开启2个任务线程执行。
任务线程死锁。
mvn compile exec:java -Dexec.mainClass=com.oldratlee.fucking.concurrency.SymmetricLockDeadlockDemo