Skip to content

Commit

Permalink
原子整数实现原理解析
Browse files Browse the repository at this point in the history
  • Loading branch information
xuMingHai1 committed Mar 22, 2022
1 parent e9560e4 commit 3fced22
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 82 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
target
11 changes: 0 additions & 11 deletions .idea/.gitignore

This file was deleted.

7 changes: 5 additions & 2 deletions .idea/java-concurrent.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 0 additions & 13 deletions .idea/libraries/Maven__net_java_dev_jna_jna_5_8_0.xml

This file was deleted.

13 changes: 0 additions & 13 deletions .idea/libraries/Maven__net_java_dev_jna_jna_platform_5_8_0.xml

This file was deleted.

13 changes: 0 additions & 13 deletions .idea/libraries/Maven__net_sf_jopt_simple_jopt_simple_4_6.xml

This file was deleted.

13 changes: 0 additions & 13 deletions .idea/libraries/Maven__org_openjdk_jcstress_jcstress_core_0_15.xml

This file was deleted.

12 changes: 12 additions & 0 deletions .run/Java Concurrency Test (Openjdk-17).run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Java Concurrency Test (Openjdk-17)" type="JarApplication">
<option name="JAR_PATH" value="$PROJECT_DIR$/concurrency-test/target/jcstress.jar" />
<option name="WORKING_DIRECTORY" value="F:\IdeaProjects\java-concurrent" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="ALTERNATIVE_JRE_PATH" value="openjdk-17" />
<module name="concurrency-test" />
<method v="2">
<option name="Maven.BeforeRunTask" enabled="true" file="$PROJECT_DIR$/pom.xml" goal="package" />
</method>
</configuration>
</component>
14 changes: 2 additions & 12 deletions concurrency-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ THE POSSIBILITY OF SUCH DAMAGE.
<packaging>jar</packaging>
<version>1.0</version>

<name>JCStress test sample</name>

<dependencies>
<dependency>
<groupId>org.openjdk.jcstress</groupId>
Expand All @@ -50,17 +48,14 @@ THE POSSIBILITY OF SUCH DAMAGE.

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>

<!--
jcstress version to use with this project.
-->
<jcstress.version>0.15</jcstress.version>

<!--
Java source/target to use for compilation.
-->
<javac.target>8</javac.target>

<!--
Name of the test Uber-JAR to generate.
-->
Expand All @@ -74,11 +69,6 @@ THE POSSIBILITY OF SUCH DAMAGE.
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.0</version>
<configuration>
<compilerVersion>${javac.target}</compilerVersion>
<source>${javac.target}</source>
<target>${javac.target}</target>
</configuration>
</plugin>

<plugin>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<logback.version>1.2.10</logback.version>
<logback.version>1.2.11</logback.version>
</properties>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
package xyz.xuminghai.atomic;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.Unsafe;

import java.util.concurrent.atomic.AtomicInteger;
import java.lang.reflect.Field;
import java.util.function.IntUnaryOperator;

/**
* 2022/3/7 11:25 星期一<br/>
* <h1>AtomicInteger和AtomicLong原理分析</h1>
* AtomicInteger本质使用的是{@link Unsafe},利用CAS机制,比较期望值和实际值,成功的话则将实际值替换为更新值
*
* @author xuMingHai
*/
@SuppressWarnings("AlibabaAvoidManuallyCreateThread")
public class AtomicIntegerAndAtomicLongDemo02 {


/**
* 日志记录器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AtomicIntegerAndAtomicLongDemo02.class);

public static void main(String[] args) {

// 多个线程共享的资源
final SimpleAtomicInteger simpleAtomicInteger = new SimpleAtomicInteger();




Expand All @@ -28,7 +40,7 @@ private static class SimpleAtomicInteger {
/**
* 用于执行不安全方法的集合
*/
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
private static final Unsafe UNSAFE;

/**
* value字段的偏移量,同一类的不同实例的字段偏移量是相同的
Expand All @@ -40,7 +52,12 @@ private static class SimpleAtomicInteger {
*/
static {
try {
VALUE_OFFSET = UNSAFE.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
theUnsafe.setAccessible(false);

VALUE_OFFSET = UNSAFE.objectFieldOffset(SimpleAtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
Expand All @@ -50,14 +67,24 @@ private static class SimpleAtomicInteger {

/**
* 获取当前值,因为value是使用volatile修饰的
*
* @return value
*/
public int get() {
return value;
}

/**
* 将当前值设置为新的值
* @param newValue 新的值
*/
public void set(int newValue) {
value = newValue;
}

/**
* 将预期值和实际值作比较,如果没有线程已经修改了,那么将值改为要更新的值
*
* @param expect 预期值
* @param update 更新值
* @return true表示更新成功,false更新失败
Expand All @@ -66,6 +93,28 @@ public boolean completeAndSet(int expect, int update) {
return UNSAFE.compareAndSwapInt(this, VALUE_OFFSET, expect, update);
}

/**
* 获取并更新原子
*
* @param intUnaryOperator 返回要更新的值
* @return 前一个值
*/
public int getAndUpdate(IntUnaryOperator intUnaryOperator) {
// 期望值,要更改的值
int prev, next;
int i = 1;
// 循环修改
do {
LOGGER.info("第{}次CAS", i++);
// 获取最新值
prev = get();
// 得到要更改的值
next = intUnaryOperator.applyAsInt(prev);
// CAS设置值
} while (!completeAndSet(prev, next));

return prev;
}


}
Expand Down

0 comments on commit 3fced22

Please sign in to comment.