-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
22517c2
commit a64fc83
Showing
3 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
68 changes: 68 additions & 0 deletions
68
concurrency-test/src/main/java/xyz/xuminghai/test/CompareDoubleCheckLockTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package xyz.xuminghai.test; | ||
|
||
import org.openjdk.jcstress.annotations.*; | ||
import org.openjdk.jcstress.infra.results.L_Result; | ||
|
||
import java.io.Serializable; | ||
|
||
/** | ||
* 2022/5/8 15:01 星期日<br/> | ||
* 和{@link DoubleCheckLockTest}比较 | ||
* @author xuMingHai | ||
*/ | ||
@JCStressTest | ||
@Outcome(id = "Instance", expect = Expect.ACCEPTABLE, desc = "OK") | ||
@Outcome(expect = Expect.ACCEPTABLE_INTERESTING, desc = "INTERESTING!!!") | ||
@State | ||
public class CompareDoubleCheckLockTest { | ||
|
||
private volatile static Instance instance; | ||
|
||
public static Instance getInstance() { | ||
Instance result = instance; | ||
if (result == null) { | ||
synchronized (CompareDoubleCheckLockTest.class) { | ||
result = instance; | ||
if (result == null) { | ||
instance = new Instance(); | ||
} | ||
} | ||
} | ||
return instance; | ||
} | ||
|
||
private static class Instance implements Serializable { | ||
private static final long serialVersionUID = -3475949357133835998L; | ||
|
||
@Override | ||
public String toString() { | ||
return "Instance"; | ||
} | ||
} | ||
|
||
/* | ||
使用4个线程测试 | ||
*/ | ||
|
||
@Actor | ||
public void actor1(L_Result r) { | ||
r.r1 = getInstance(); | ||
} | ||
|
||
@Actor | ||
public void actor2(L_Result r) { | ||
r.r1 = getInstance(); | ||
} | ||
|
||
@Actor | ||
public void actor3(L_Result r) { | ||
r.r1 = getInstance(); | ||
} | ||
|
||
@Actor | ||
public void actor4(L_Result r) { | ||
r.r1 = getInstance(); | ||
} | ||
|
||
|
||
} |
89 changes: 89 additions & 0 deletions
89
concurrency-test/src/main/java/xyz/xuminghai/test/DoubleCheckLockTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package xyz.xuminghai.test; | ||
|
||
import org.openjdk.jcstress.annotations.*; | ||
import org.openjdk.jcstress.infra.results.L_Result; | ||
|
||
import java.io.Serializable; | ||
|
||
/** | ||
* 2022/5/8 14:47 星期日<br/> | ||
* 双重检查锁单例<br/> | ||
* <p>在维基百科中的<a href="https://zh.m.wikipedia.org/zh-cn/%E5%8F%8C%E9%87%8D%E6%A3%80%E6%9F%A5%E9%94%81%E5%AE%9A%E6%A8%A1%E5%BC%8F">双重检查锁</a>,使用了局部变量代替直接比较 volatile 修饰的变量</p> | ||
* 以下来自 Joshua Bloch "Effective Java, Second Edition", p. 283 | ||
* <pre> | ||
* //Double-check idiom for lazy initialization of instance fields | ||
* private volatile FieldType field; | ||
* Fie1dType getFie1d() { | ||
* FieldType result= field; | ||
* if(result == nu11) { // First check (no locking) | ||
* synchronized(this) { | ||
* result = field; | ||
* if (result == nul1) // Second check (with locking) | ||
* field = result = computeFieldValue(); | ||
* } | ||
* } | ||
* return result; | ||
* } | ||
* </pre> | ||
* 这段代码可能看起来似乎有些费解。尤其对于需要用到局部变量result可能有点不解。 | ||
* 这个变量的作用是确保field只在已经被初始化的情况下读取一次。虽然这不是严格需要,但是可以提升性能,并且因为给低级的并发编程应用了一些标准,因此更加优雅。 | ||
* 在我的机器上,上述的方法比没用局部变量的方法快了大约25%。 | ||
* @author xuMingHai | ||
*/ | ||
@JCStressTest | ||
@Outcome(id = "Instance", expect = Expect.ACCEPTABLE, desc = "OK") | ||
@Outcome(expect = Expect.ACCEPTABLE_INTERESTING, desc = "INTERESTING!!!") | ||
@State | ||
public class DoubleCheckLockTest { | ||
|
||
private volatile static Instance instance; | ||
|
||
public static Instance getInstance() { | ||
Instance result = instance; | ||
if (result == null) { | ||
synchronized (DoubleCheckLockTest.class) { | ||
result = instance; | ||
if (result == null) { | ||
instance = new Instance(); | ||
} | ||
} | ||
} | ||
return instance; | ||
} | ||
|
||
private static class Instance implements Serializable { | ||
|
||
private static final long serialVersionUID = -3949564844175144101L; | ||
|
||
@Override | ||
public String toString() { | ||
return "Instance"; | ||
} | ||
} | ||
|
||
/* | ||
使用4个线程测试 | ||
*/ | ||
|
||
@Actor | ||
public void actor1(L_Result r) { | ||
r.r1 = getInstance(); | ||
} | ||
|
||
@Actor | ||
public void actor2(L_Result r) { | ||
r.r1 = getInstance(); | ||
} | ||
|
||
@Actor | ||
public void actor3(L_Result r) { | ||
r.r1 = getInstance(); | ||
} | ||
|
||
@Actor | ||
public void actor4(L_Result r) { | ||
r.r1 = getInstance(); | ||
} | ||
|
||
|
||
} |