竹笋

首页 » 问答 » 环境 » 并发编程从一个程序入门synchro
TUhjnbcbe - 2023/3/22 20:35:00

看这么一段代码,思考为什么结果不是0?

publicclassSyncDemo{privatestaticintcount=0;publicstaticvoidincrement(){count++;}publicstaticvoiddecrement(){count--;}publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt1=newThread(()-{for(inti=0;i;i++){increment();}},"t1");Threadt2=newThread(()-{for(inti=0;i;i++){decrement();}},"t2");t1.start();t2.start();t1.join();t2.join();System.out.println(count);}}

问题分析

Java中对静态变量的自增,自减并不是原子操作。

i++的JVM字节码指令

getstatici//获取静态变量i的值iconst_1//将int常量1压入操作数栈iadd//自增

i--的JVM字节码指令

getstatici//获取静态变量i的值iconst_1//将int常量1压入操作数栈isub//自减

临界区(CriticalSection)

我们知道一个程序可以运行多个线程是没有任何问题的。但是多个线程去读共享资源,也是没有问题的!在多个线程对共享资源读写操作时发生指令交错,就会出现问题!一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区,其共享资源为临界资源。往简单说,上面的i--与i++的代码块就是临界区。

竞态条件(RaceCondition)

多个线程在临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之为发生了竞态条件。阻塞式的解决方案:synchronized,Lock非阻塞式的解决方案:原子变量

synchronized解决结果不为0的问题

第一种方式

publicsynchronizedstaticvoidincrement(){count++;}publicstaticsynchronizedvoiddecrement(){count--;}

第二种方式

privatestaticStringlock="";publicstaticvoidincrement(){synchronized(lock){count++;}}publicstaticvoiddecrement(){synchronized(lock){count--;}}

不同位置的synchronized有什么区别呢?

image.png

结束语

本文只说synchronized的基础使用。深入研究请

1
查看完整版本: 并发编程从一个程序入门synchro