-3, 接收到数据 : Thread-0:5 当前消费线程 : Thread-3, 接收到数据 : Thread-0:7 当前消费线程 : Thread-3, 接收到数据 : Thread-0:8 当前消费线程 : Thread-3, 接收到数据 : Thread-0:9 当前消费线程 : Thread-3, 接收到数据 : Thread-2:0 当前消费线程 : Thread-3, 接收到数据 : Thread -2:1 当前消费线程 : Thread-3, 接收到数据 : Thread-2:2 当前消费线程 : Thread-3, 接收到数据 : Thread-2:3 当前消费线程 : Thread-3, 接收到数据 : Thread-2:4 当前消费线程 : Thread-3, 接收到数据 : Thread-2:5 当前消费线程 : Thread-3, 接收到数据 : Thread-2:6 当前消费线程 : Thread -3, 接收到数据 : Thread-2:7 当前消费线程 : Thread-3, 接收到数据 : Thread-2:8 当前消费线程 : Thread-3, 接收到数据 : Thread-2:9 当前消费线程
Thread-3消费者准备消费集合元素! Thread-0生成完成:[java] Thread-0生产者准备生产集合元素! Thread-3消费完成:[java] Thread-3消费者准备消费集合元素! Thread-2生成完成:[java] Thread-2生产者准备生产集合元素! Thread-3消费完成:[java] Thread-3消费者准备消费集合元素! Thread-0生成完成:[Struts] Thread-0生产者准备生产集合元素! Thread-3消费完成:[Struts] Thread-3消费者准备消费集合元素!
started 140353613993728)>]after query item desc: <Thread(Thread-1, started 140353630779136)> [<Thread(Thread -3, started 140001957750528)>]after update item desc: <Thread(Thread-3, started 140001957750528)> [<Thread (Thread-2, started 140001966143232)>]after query item desc: <Thread(Thread-3, started 140001957750528 -3, started 139633869813504)>]update fun after update item desc: <Thread(Thread-3, started 139633869813504 )> [<Thread(Thread-2, started 139890835904256)>]get fun after query item desc: <Thread(Thread-3, started
-3已消费,剩余商品数量:0 生产者Thread-0已生产完成,商品数量:1 消费者Thread-3已消费,剩余商品数量:0 生产者Thread-2已生产完成,商品数量:1 消费者Thread- 1已消费,剩余商品数量:0 生产者Thread-0已生产完成,商品数量:1 生产者Thread-2已生产完成,商品数量:2 消费者Thread-1已消费,剩余商品数量:1 消费者Thread-3 已消费,剩余商品数量:0 生产者Thread-0已生产完成,商品数量:1 消费者Thread-1已消费,剩余商品数量:0 生产者Thread-2已生产完成,商品数量:1 消费者Thread-3已消费 ,剩余商品数量:0 生产者Thread-0已生产完成,商品数量:1 消费者Thread-1已消费,剩余商品数量:0 生产者Thread-2已生产完成,商品数量:1 消费者Thread-3已消费, -3已生产完成,商品数量:1 消费者Thread-1已消费,剩余商品数量:0 生产者Thread-0已生产完成,商品数量:1 生产者Thread-3已生产完成,商品数量:2 消费者Thread-
} catch (Exception e) { e.printStackTrace(); } } } } 执行结果 Thread 到达栅栏 A Thread-4 到达栅栏 A Thread-0 到达栅栏 A Thread-2 到达栅栏 A Thread-1 到达栅栏 A Thread-0 完成最后任务 Thread-0 冲破栅栏 A Thread 冲破栅栏 A Thread-1 冲破栅栏 A Thread-2 冲破栅栏 A Thread-1 到达栅栏 B Thread-2 到达栅栏 B Thread-4 到达栅栏 B Thread-0 到达栅栏 B Thread -3 到达栅栏 B Thread-3 完成最后任务 Thread-3 冲破栅栏 B Thread-1 冲破栅栏 B Thread-2 冲破栅栏 B Thread-4 冲破栅栏 B Thread-0 冲破栅栏
我们假设上述代码中的3条语句分别由3个线程执行,并假如这3个线程分别是thread-1、thread-2、thread-3。 原因就是根据happens-before原则,thread-1先行发生于thread-2,所以thread-1执行后的值,thread-2是可以获取到的,并且我们假设thread-3没有执行。 也就是说thread-2和thread-3谁先执行并不是确定的。如果thread-3在thread-2之前执行的,那么thread-2中变量j的值是多少呢?答案可想而知,变量j的值是不确定的。 因为我们并不确定thread-1和thread-3到底谁先执行。 如果thread-3比thread-1先执行,那么因为thread-1和thread-2有happens-before关系,所以并不会对变量j的值产生影响,但如果thread-1比thread-3先执行
got resB Thread-1 got resA Thread-2 got resA Thread-2 got resB Thread-2 got resB Thread-2 got resA Thread -3 got resA Thread-3 got resB Thread-3 got resB Thread-3 got resA Thread-5 got resA Thread-5 got resB t = MyThread() t.start() if __name__ == '__main__': test() 执行结果: Thread-1 set num to 1 Thread
实践效果 下面是注入 Byteman 脚本前后,控制台输出日志变化情况: Thread-3 7 Thread-3 8 Thread-2 9 Thread-3 10 Thread -2 11 setThreadName Thread-2 setThreadName Thread-2 Thread-3 持有锁 Thread-3 12 setThreadName Thread-3 Thread-2 持有锁 Thread-2 12 setThreadName Thread-2 Thread-3 持有锁 Thread-3 13 setThreadName Thread-3 Thread-2 持有锁 Thread-2 13 setThreadName Thread-2 可以看出,注入前,看着似乎是线程安全的
Thread-2 10 Thread-2 11 Thread-2 12 Thread-4 13 Thread-4 14 Thread-4 15 Thread-4 16 Thread-4 17 Thread -3 3 Thread-3 18 Thread-3 19 Thread-3 20 Thread-3 21 Thread-1 2 Thread-1 22 Thread-1 23 Thread 2 Thread-4 3 Thread-4 4 Thread-4 5 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 Thread-1 5 Thread -3 1 Thread-3 2 Thread-3 3 Thread-3 4 Thread-3 5 ---- 实际上,第一张未使用 ThreadLocal 的情况下,也可以让线程运行时,操作自己独立的
,倒数开始: Thread-2 3 第3个线程,倒数开始: Thread-3 3 第3个线程,倒数开始: Thread-3 2 第2个线程,倒数开始: Thread-2 2 第1个线程,倒数开始: Thread Thread-1 : 倒数开始:3 Thread-2 : 倒数开始:3 Thread-3 : 倒数开始:3 Thread-1 : 倒数开始:2 Thread-3 : 倒数开始:2 Thread -3 : 倒数开始:3 thread-3 : 倒数开始:2 thread-1 : 倒数开始:2 thread-2 : 倒数开始:2 thread-3 : 倒数开始:1 thread-2 : -3 : lock.... thread-3 : 倒数开始:3 thread-3 : 倒数开始:2 thread-3 : 倒数开始:1 thread-3 : open again MainThread Thread-2 : after add:2 Thread-3 : before add:2 执行了1s之后。。。
同时, 如果释放锁的线程, 再次尝试获取锁的概率, 会非常高. sync = [Thread[Thread-2,5,main], Thread[Thread-3,5,main], Thread[Thread 7,5,main], Thread[Thread-8,5,main], Thread[Thread-9,5,main]] sync = [Thread[Thread-2,5,main], Thread[Thread 7,5,main], Thread[Thread-8,5,main], Thread[Thread-9,5,main], Thread[Thread-0,5,main]] sync = [Thread[Thread 7,5,main], Thread[Thread-8,5,main], Thread[Thread-9,5,main], Thread[Thread-0,5,main]] sync = [Thread[Thread 7,5,main], Thread[Thread-8,5,main], Thread[Thread-9,5,main], Thread[Thread-0,5,main]] sync = [Thread[Thread
Thread-3 is waiting semaphore. Thread-0 release semaphore. Thread-3 acquired semaphore(Thu Oct 25 20:33:23 2018). Thread-1 release semaphore. Thread-3 release semaphore. 可以看到Thread-3是在Thread-0释放后才获得信号对象。
-3 完成了任务 Thread-3 即将执行任务4 Thread-2 完成了任务 Thread-2 即将执行任务5 Thread-1 完成了任务 Thread-1 即将执行任务6 Thread-0 完成了任务 Thread-0 即将执行任务7 Thread-1 完成了任务 Thread-3 完成了任务 Thread-1 即将执行任务8 Thread-3 即将执行任务9 Thread-0 完成了任务 Thread -2 完成了任务 Thread-2 即将执行任务10 Thread-0 即将执行任务11 Thread-3 完成了任务 Thread-1 完成了任务 Thread-1 即将执行任务12 Thread-3 -3 完成了任务 Thread-3 即将执行任务17 Thread-2 完成了任务 Thread-0 完成了任务 Thread-0 即将执行任务19 Thread-2 即将执行任务18 Thread-3 Thread-2 即将执行任务23 Thread-1 完成了任务 Thread-3 完成了任务 Thread-0 完成了任务 Thread-2 完成了任务 4.
| | Thread-1 | | Thread-2 |----> +---------------+ <----| Thread-2 | | Thread -3 | | A Thread-2 | | Thread-3 | +------------------+ +------------ | | Thread-1 | | Thread-2 |----> +---------------+ <----| Thread-2 | | Thread -3 | | A Thread-2 | | Thread-3 | +------------------+ | B Thread-1 | +------------------+ | B Thread-3 | | A
InterruptedException e) { e.printStackTrace(); } } } 控制台打印 Thread-4获取 lockB 成功 Thread -3获取 lockA 成功 Thread-3尝试获取 lockB Thread-4尝试获取 lockA 我们可以发现 Thread-3 获取 lockA 成功后尝试获取 lockB 一直不能成功。 lock Monitor@0x000000001f0134f8 (Object@0x00000007721d90f0, a java/lang/Object), which is held by "Thread -3" "Thread-3": waiting to lock Monitor@0x000000001f011ef8 (Object@0x00000007721d90e0, a java/lang/ Thread-4获取 lockA 成功 Thread-4尝试获取 lockB Thread-4获取 lockB 成功 Thread-3获取 lockA 成功 Thread-3尝试获取 lockB Thread
-3消费者****100 Thread-0生产者------------101 Thread-3消费者****101 Thread-2消费者****101 Thread-1生产者------------ 102 Thread-3消费者****102 Thread-0生产者------------103 Thread-2消费者****103 Thread-1生产者------------104 Thread Thread-1生产者------------105 Thread-0生产者------------106 Thread-2消费者****106 Thread-1生产者------------107 Thread -3消费者****416 Thread-1生产者------------417 Thread-3消费者****417 Thread-0生产者------------418 Thread-2消费者**** 418 Thread-0生产者------------419 Thread-3消费者****419 Thread-1生产者------------420 Thread-2消费者****420 以上就大功告成了
| | Thread-1 | | Thread-2 |----> +---------------+ <----| Thread-2 | | Thread -3 | | A Thread-2 | | Thread-3 | +------------------+ +------------ | | Thread-1 | | Thread-2 |----> +---------------+ <----| Thread-2 | | Thread -3 | | A Thread-2 | | Thread-3 | +------------------+ | B Thread-1 | +------------------+ | B Thread-3 | | A
()); }).start(); } } } 运行结果 读取Thread-0 读取Thread-2 读取Thread-1 读取Thread-4 读取Thread Thread-6 读取Thread-7 后续操作Thread-7 后续操作Thread-0 后续操作Thread-1 后续操作Thread-5 后续操作Thread-2 后续操作Thread-6 后续操作Thread + Thread.currentThread().getName()); }).start(); } } } 运行结果 读取Thread-0 读取Thread Thread-4 读取Thread-6 读取Thread-7 Thread-1额外任务执行 后续操作Thread-1 后续操作Thread-0 后续操作Thread-5 后续操作Thread-7 后续操作Thread -3 读取Thread-4 后续操作Thread-4 后续操作Thread-0 后续操作Thread-2 后续操作Thread-3 后续操作Thread-1 CyclicBarrier复用 读取Thread
Thread-3 准备取数据。Thread-3 已经取走数据,队列眼下有: 2 个数据!Thread-1 准备放数据!Thread-1 已经放了数据,队列眼下有: 3 个数据。 Thread-3 准备取数据!Thread-3 已经取走数据,队列眼下有: 2 个数据!Thread-0 已经放了数据,队列眼下有: 3 个数据。Thread-1 准备放数据! Thread-3 准备取数据!Thread-3 已经取走数据。队列眼下有: 2 个数据!Thread-2 已经放了数据,队列眼下有: 3 个数据! 三.
线程Thread-3正在写入数据... 线程Thread-1写入数据完毕,等待其他线程写入完毕 线程Thread-2写入数据完毕,等待其他线程写入完毕 线程Thread-0写入数据完毕,等待其他线程写入完毕 线程Thread-3写入数据完毕, 线程Thread-3获得分布式锁 线程Thread-3释放分布式锁 END 线程Thread-1获得分布式锁 线程Thread-1释放分布式锁 END 线程Thread-2获得分布式锁 线程Thread