第一篇文章
优化前
问题描述:
有二十个线程,前十个线程,每个线程分别对共享变量进行加 1 操作,循环 10 次
后十个线程,每个线程对共享变量进行减 1 操作,循环 10 次
每个线程操作后,输出共享变量的值
直接代码:
package com.yhm.testSpringMvc.Thread;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicClassTestBefore {
private static Integer integer = new Integer(100);
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new yhmDecrementClass()).start();
new Thread(new yhmIncrementClass()).start();
}
}
static class yhmIncrementClass implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "," + integer++);
}
}
}
static class yhmDecrementClass implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "," + integer--);
}
}
}
}
输出结果:
D:\JAVA\jdk8_64\bin\java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:59643,suspend=y,server=n -Dfile.encoding=UTF-8 -classpath "D:\JAVA\jdk8_64\jre\lib\charsets.jar;D:\JAVA\jdk8_64\jre\lib\deploy.jar;D:\JAVA\jdk8_64\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk8_64\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk8_64\jre\lib\ext\dnsns.jar;D:\JAVA\jdk8_64\jre\lib\ext\jaccess.jar;D:\JAVA\jdk8_64\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk8_64\jre\lib\ext\localedata.jar;D:\JAVA\jdk8_64\jre\lib\ext\nashorn.jar;D:\JAVA\jdk8_64\jre\lib\ext\sunec.jar;D:\JAVA\jdk8_64\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk8_64\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk8_64\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk8_64\jre\lib\ext\zipfs.jar;D:\JAVA\jdk8_64\jre\lib\javaws.jar;D:\JAVA\jdk8_64\jre\lib\jce.jar;D:\JAVA\jdk8_64\jre\lib\jfr.jar;D:\JAVA\jdk8_64\jre\lib\jfxswt.jar;D:\JAVA\jdk8_64\jre\lib\jsse.jar;D:\JAVA\jdk8_64\jre\lib\management-agent.jar;D:\JAVA\jdk8_64\jre\lib\plugin.jar;D:\JAVA\jdk8_64\jre\lib\resources.jar;D:\JAVA\jdk8_64\jre\lib\rt.jar;D:\ideaPros\codeGitee\ACM\target\classes;D:\repo\junit\junit\4.12\junit-4.12.jar;D:\repo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\repo\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar;D:\repo\org\springframework\spring-core\4.2.5.RELEASE\spring-core-4.2.5.RELEASE.jar;D:\repo\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\repo\org\springframework\spring-beans\4.2.5.RELEASE\spring-beans-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-context\4.2.5.RELEASE\spring-context-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-aop\4.2.5.RELEASE\spring-aop-4.2.5.RELEASE.jar;D:\repo\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;D:\repo\org\springframework\spring-expression\4.2.5.RELEASE\spring-expression-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-tx\4.2.5.RELEASE\spring-tx-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-web\4.2.5.RELEASE\spring-web-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-webmvc\4.2.5.RELEASE\spring-webmvc-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-test\4.2.5.RELEASE\spring-test-4.2.5.RELEASE.jar;D:\repo\org\slf4j\slf4j-log4j12\1.6.6\slf4j-log4j12-1.6.6.jar;D:\repo\org\slf4j\slf4j-api\1.6.6\slf4j-api-1.6.6.jar;D:\repo\log4j\log4j\1.2.17\log4j-1.2.17.jar;D:\repo\cglib\cglib-nodep\3.2.2\cglib-nodep-3.2.2.jar;D:\repo\org\aspectj\aspectjweaver\1.7.4\aspectjweaver-1.7.4.jar;D:\repo\com\alibaba\dubbo\2.5.3\dubbo-2.5.3.jar;D:\repo\org\springframework\spring\2.5.6.SEC03\spring-2.5.6.SEC03.jar;D:\repo\org\javassist\javassist\3.15.0-GA\javassist-3.15.0-GA.jar;D:\repo\org\jboss\netty\netty\3.2.5.Final\netty-3.2.5.Final.jar;D:\chengxu\intelliJIDEA\IntelliJ IDEA 2017.3.5\lib\idea_rt.jar" com.yhm.testSpringMvc.Thread.AtomicClassTestBefore Connected to the target VM, address: '127.0.0.1:59643', transport: 'socket' Thread-0,100 Thread-0,99 Thread-0,98 Thread-0,97 Thread-0,96 Thread-0,95 Thread-0,94 Thread-0,93 Thread-0,92 Thread-0,91 Thread-2,91 Thread-2,89 Thread-2,88 Thread-2,87 Thread-4,90 Thread-4,85 Thread-3,90 Thread-3,83 Thread-3,84 Thread-1,90 Thread-3,85 Thread-5,84 Thread-4,84 Thread-11,89 Thread-11,89 Thread-9,90 Thread-2,85 Thread-10,92 Thread-10,90 Thread-10,89 Thread-10,88 Thread-6,86 Thread-15,86 Thread-15,86 Thread-15,87 Thread-10,87 Thread-10,89 Thread-10,87 Thread-10,86 Thread-10,85 Thread-10,85 Thread-14,91 Thread-13,91 Thread-13,83 Thread-13,84 Thread-13,85 Thread-2,92 Thread-2,87 Thread-2,86 Thread-2,85 Thread-2,84 Thread-9,91 Thread-11,90 Thread-12,91 Thread-12,85 Thread-12,84 Thread-12,83 Thread-12,82 Thread-4,90 Thread-5,88 Thread-8,89 Thread-8,80 Thread-8,79 Thread-8,78 Thread-8,77 Thread-8,76 Thread-3,88 Thread-3,74 Thread-3,75 Thread-3,76 Thread-3,77 Thread-3,78 Thread-7,87 Thread-1,86 Thread-7,79 Thread-7,81 Thread-7,82 Thread-7,83 Thread-7,84 Thread-7,85 Thread-7,86 Thread-7,87 Thread-7,88 Thread-8,75 Thread-8,89 Thread-5,79 Thread-4,80 Thread-12,81 Thread-12,87 Thread-12,86 Thread-12,85 Thread-12,84 Thread-11,84 Thread-9,83 Thread-13,86 Thread-14,84 Thread-19,84 Thread-18,88 Thread-18,86 Thread-18,85 Thread-18,84 Thread-18,83 Thread-18,82 Thread-18,81 Thread-18,80 Thread-18,79 Thread-18,78 Thread-17,88 Thread-17,77 Thread-17,78 Thread-15,87 Thread-15,79 Thread-16,88 Thread-6,87 Thread-6,80 Thread-16,81 Thread-15,80 Thread-15,77 Thread-15,78 Thread-15,79 Thread-15,80 Thread-17,79 Thread-19,85 Thread-14,86 Thread-13,85 Thread-9,84 Thread-11,83 Thread-11,84 Thread-11,85 Thread-11,86 Thread-11,87 Thread-11,88 Thread-4,88 Thread-4,89 Thread-4,88 Thread-4,87 Thread-4,86 Thread-5,87 Thread-8,88 Thread-1,80 Thread-8,86 Thread-5,85 Thread-9,83 Thread-9,87 Thread-9,88 Thread-9,89 Thread-9,90 Thread-13,82 Thread-13,92 Thread-14,83 Thread-14,94 Thread-14,93 Thread-19,82 Thread-19,91 Thread-19,92 Thread-19,93 Thread-19,94 Thread-19,95 Thread-19,96 Thread-19,97 Thread-17,81 Thread-17,98 Thread-16,78 Thread-16,100 Thread-16,99 Thread-16,98 Thread-16,97 Thread-16,96 Thread-16,95 Thread-16,94 Thread-6,79 Thread-17,99 Thread-14,92 Thread-14,93 Thread-14,92 Thread-14,91 Thread-13,93 Thread-13,90 Thread-9,91 Thread-5,86 Thread-1,85 Thread-1,92 Thread-1,93 Thread-1,94 Thread-1,95 Thread-5,91 Thread-17,92 Thread-6,93 Thread-17,98 Thread-17,98 Thread-5,97 Thread-5,99 Thread-5,100 Thread-1,96 Thread-6,99 Thread-6,102 Thread-6,101 Thread-6,100 Thread-6,99 Thread-1,101 Disconnected from the target VM, address: '127.0.0.1:59643', transport: 'socket' Process finished with exit code 0
从结果可以看到,最后输出的结果并非 100(共享变量初始值 100)
原因分析:
JAVA 中每个线程对共享变量的操作并非同步进行,为了提升线程的运行速度,对每个线程都有单独的内存分配,即共享变量只有一个,但是每个线程复制了一份到自己的内存区域内。A 线程对共享变量的操作,实际上是对自己单独内存区域内变量的操作,操作完成后并不会马上改变共享变量的值,可以说各自在干着自己线程的事情。
解决办法:需要线程同步,每个线程对共享变量的操作应该马上生效!
优化后
package com.yhm.testSpringMvc.Thread;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicClassTest {
private static AtomicInteger atomicInteger = new AtomicInteger(100);
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new yhmDecrementClass()).start();
new Thread(new yhmIncrementClass()).start();
}
}
static class yhmIncrementClass implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "," + atomicInteger.decrementAndGet());
}
}
}
static class yhmDecrementClass implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "," + atomicInteger.incrementAndGet());
}
}
}
}
输出结果:
D:\JAVA\jdk8_64\bin\java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:60088,suspend=y,server=n -Dfile.encoding=UTF-8 -classpath "D:\JAVA\jdk8_64\jre\lib\charsets.jar;D:\JAVA\jdk8_64\jre\lib\deploy.jar;D:\JAVA\jdk8_64\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk8_64\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk8_64\jre\lib\ext\dnsns.jar;D:\JAVA\jdk8_64\jre\lib\ext\jaccess.jar;D:\JAVA\jdk8_64\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk8_64\jre\lib\ext\localedata.jar;D:\JAVA\jdk8_64\jre\lib\ext\nashorn.jar;D:\JAVA\jdk8_64\jre\lib\ext\sunec.jar;D:\JAVA\jdk8_64\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk8_64\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk8_64\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk8_64\jre\lib\ext\zipfs.jar;D:\JAVA\jdk8_64\jre\lib\javaws.jar;D:\JAVA\jdk8_64\jre\lib\jce.jar;D:\JAVA\jdk8_64\jre\lib\jfr.jar;D:\JAVA\jdk8_64\jre\lib\jfxswt.jar;D:\JAVA\jdk8_64\jre\lib\jsse.jar;D:\JAVA\jdk8_64\jre\lib\management-agent.jar;D:\JAVA\jdk8_64\jre\lib\plugin.jar;D:\JAVA\jdk8_64\jre\lib\resources.jar;D:\JAVA\jdk8_64\jre\lib\rt.jar;D:\ideaPros\codeGitee\ACM\target\classes;D:\repo\junit\junit\4.12\junit-4.12.jar;D:\repo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\repo\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar;D:\repo\org\springframework\spring-core\4.2.5.RELEASE\spring-core-4.2.5.RELEASE.jar;D:\repo\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\repo\org\springframework\spring-beans\4.2.5.RELEASE\spring-beans-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-context\4.2.5.RELEASE\spring-context-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-aop\4.2.5.RELEASE\spring-aop-4.2.5.RELEASE.jar;D:\repo\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;D:\repo\org\springframework\spring-expression\4.2.5.RELEASE\spring-expression-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-tx\4.2.5.RELEASE\spring-tx-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-web\4.2.5.RELEASE\spring-web-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-webmvc\4.2.5.RELEASE\spring-webmvc-4.2.5.RELEASE.jar;D:\repo\org\springframework\spring-test\4.2.5.RELEASE\spring-test-4.2.5.RELEASE.jar;D:\repo\org\slf4j\slf4j-log4j12\1.6.6\slf4j-log4j12-1.6.6.jar;D:\repo\org\slf4j\slf4j-api\1.6.6\slf4j-api-1.6.6.jar;D:\repo\log4j\log4j\1.2.17\log4j-1.2.17.jar;D:\repo\cglib\cglib-nodep\3.2.2\cglib-nodep-3.2.2.jar;D:\repo\org\aspectj\aspectjweaver\1.7.4\aspectjweaver-1.7.4.jar;D:\repo\com\alibaba\dubbo\2.5.3\dubbo-2.5.3.jar;D:\repo\org\springframework\spring\2.5.6.SEC03\spring-2.5.6.SEC03.jar;D:\repo\org\javassist\javassist\3.15.0-GA\javassist-3.15.0-GA.jar;D:\repo\org\jboss\netty\netty\3.2.5.Final\netty-3.2.5.Final.jar;D:\chengxu\intelliJIDEA\IntelliJ IDEA 2017.3.5\lib\idea_rt.jar" com.yhm.testSpringMvc.Thread.AtomicClassTest Connected to the target VM, address: '127.0.0.1:60088', transport: 'socket' Thread-0,101 Thread-0,102 Thread-0,103 Thread-0,104 Thread-0,105 Thread-0,106 Thread-0,107 Thread-0,108 Thread-0,109 Thread-0,110 Thread-1,109 Thread-2,110 Thread-3,108 Thread-3,108 Thread-3,108 Thread-1,109 Thread-6,107 Thread-3,106 Thread-5,107 Thread-4,109 Thread-4,105 Thread-4,107 Thread-4,108 Thread-4,108 Thread-4,109 Thread-4,111 Thread-2,109 Thread-11,111 Thread-11,111 Thread-11,111 Thread-11,110 Thread-11,109 Thread-2,112 Thread-2,109 Thread-4,112 Thread-4,110 Thread-10,110 Thread-9,107 Thread-9,111 Thread-9,110 Thread-9,110 Thread-9,108 Thread-9,107 Thread-9,106 Thread-9,105 Thread-9,104 Thread-9,103 Thread-8,106 Thread-8,104 Thread-8,105 Thread-8,106 Thread-8,107 Thread-8,108 Thread-8,109 Thread-8,110 Thread-8,111 Thread-8,112 Thread-5,104 Thread-3,105 Thread-7,106 Thread-6,107 Thread-6,110 Thread-6,111 Thread-1,106 Thread-6,112 Thread-7,109 Thread-3,110 Thread-3,110 Thread-5,111 Thread-19,109 Thread-18,111 Thread-17,112 Thread-17,107 Thread-17,106 Thread-10,113 Thread-16,112 Thread-16,107 Thread-16,108 Thread-16,109 Thread-16,110 Thread-16,111 Thread-16,112 Thread-16,113 Thread-16,114 Thread-16,115 Thread-4,111 Thread-2,109 Thread-2,116 Thread-15,108 Thread-14,108 Thread-11,107 Thread-11,116 Thread-13,108 Thread-12,112 Thread-12,115 Thread-12,116 Thread-12,117 Thread-12,118 Thread-12,119 Thread-12,120 Thread-12,121 Thread-12,122 Thread-12,123 Thread-13,114 Thread-13,122 Thread-13,121 Thread-13,120 Thread-13,119 Thread-13,118 Thread-11,115 Thread-14,117 Thread-15,116 Thread-2,117 Thread-2,117 Thread-10,106 Thread-17,105 Thread-18,108 Thread-18,119 Thread-18,120 Thread-18,121 Thread-18,122 Thread-18,123 Thread-18,124 Thread-18,125 Thread-19,107 Thread-5,108 Thread-5,124 Thread-5,123 Thread-5,122 Thread-5,121 Thread-5,120 Thread-5,119 Thread-3,109 Thread-3,118 Thread-7,111 Thread-6,112 Thread-6,117 Thread-6,118 Thread-6,119 Thread-6,120 Thread-1,111 Thread-7,116 Thread-3,117 Thread-19,125 Thread-19,117 Thread-19,116 Thread-19,115 Thread-19,114 Thread-19,113 Thread-19,112 Thread-19,111 Thread-18,126 Thread-17,118 Thread-17,110 Thread-17,109 Thread-2,119 Thread-10,118 Thread-10,110 Thread-10,111 Thread-10,112 Thread-10,113 Thread-10,114 Thread-15,116 Thread-15,114 Thread-15,113 Thread-15,112 Thread-15,111 Thread-15,110 Thread-15,109 Thread-15,108 Thread-14,117 Thread-11,116 Thread-13,117 Thread-11,108 Thread-14,109 Thread-10,115 Thread-2,109 Thread-17,108 Thread-7,118 Thread-7,106 Thread-7,105 Thread-1,119 Thread-7,104 Thread-17,107 Thread-14,108 Thread-13,107 Thread-14,102 Thread-17,101 Thread-7,102 Thread-7,101 Thread-1,103 Thread-14,102 Thread-13,101 Thread-14,101 Thread-14,102 Thread-14,103 Thread-1,100 Thread-1,102 Thread-1,101 Thread-1,100 Disconnected from the target VM, address: '127.0.0.1:60088', transport: 'socket' Process finished with exit code 0
可以看到,最后一个线程的最后一次操作,得到的值是 100,即所有线程的操作是对同一个变量进行的。每个线程对变量的改变,对于其他线程都是生效的
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于