Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
怪我冷i
MyAtomicInteger
提交
cc01756c
M
MyAtomicInteger
项目概览
怪我冷i
/
MyAtomicInteger
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
MyAtomicInteger
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
cc01756c
编写于
10月 13, 2020
作者:
Z
zhouwangwang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add README
上级
374bc7df
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
155 addition
and
0 deletion
+155
-0
README.md
README.md
+155
-0
未找到文件。
README.md
0 → 100644
浏览文件 @
cc01756c
# 用Unsafe实现AtomicInteger类
**原理**
AtomicInteger可以在并发情况下达到原子化更新,避免使用了synchronized,而且性能非常高。
![
在这里插入图片描述
](
https://img-blog.csdnimg.cn/img_convert/7fa0b413ccc4eebf79a7d3f4fa8ba5e6.png#pic_center
)
AtomicInteger的底层是用Unsafe来实现的,这里我们手写一个AtomicInteger类,并且测试一下。
**测试例子**
启动 1000 个线程,每个线程做 -10 元 的操作,如果初始余额为 10000 那么正确的结果应当是 0。
以下代码在JDK1.8通过测试。
## 账户Account 类
```
java
interface
Account
{
// 获取余额
Integer
getBalance
();
// 取款
void
withdraw
(
Integer
amount
);
/**
* 方法内会启动 1000 个线程,每个线程做 -10 元 的操作
* 如果初始余额为 10000 那么正确的结果应当是 0
*/
static
void
demo
(
Account
account
)
{
List
<
Thread
>
ts
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
ts
.
add
(
new
Thread
(()
->
{
account
.
withdraw
(
10
);
}));
}
long
start
=
System
.
nanoTime
();
ts
.
forEach
(
Thread:
:
start
);
ts
.
forEach
(
t
->
{
try
{
t
.
join
();
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
});
long
end
=
System
.
nanoTime
();
System
.
out
.
println
(
account
.
getBalance
()
+
" cost: "
+
(
end
-
start
)/
1000_000
+
" ms"
);
}
}
```
## Account 实现类
```
java
class
DiyAccount
implements
Account
{
private
DiyAtomicInteger
balance
;
public
DiyAccount
(
int
balance
)
{
this
.
balance
=
new
DiyAtomicInteger
(
balance
);
}
@Override
public
Integer
getBalance
()
{
return
balance
.
getValue
();
}
@Override
public
void
withdraw
(
Integer
amount
)
{
balance
.
decrement
(
amount
);
}
}
```
## DiyAtomicInteger 类
```
java
class
DiyAtomicInteger
{
private
volatile
int
value
;
//实例操作的变量
private
static
final
long
valueOffset
;
//偏移量
private
static
final
Unsafe
UNSAFE
;
// unsafe实例对象
static
{
UNSAFE
=
UnsafeAccessor
.
getUnsafe
();
try
{
valueOffset
=
UNSAFE
.
objectFieldOffset
(
DiyAtomicInteger
.
class
.
getDeclaredField
(
"value"
));
}
catch
(
NoSuchFieldException
e
)
{
e
.
printStackTrace
();
throw
new
RuntimeException
(
e
);
}
}
public
int
getValue
()
{
return
value
;
}
public
void
decrement
(
int
amount
)
{
while
(
true
)
{
int
prev
=
this
.
value
;
int
next
=
prev
-
amount
;
if
(
UNSAFE
.
compareAndSwapInt
(
this
,
valueOffset
,
prev
,
next
))
{
break
;
}
}
}
public
DiyAtomicInteger
(
int
value
)
{
this
.
value
=
value
;
}
}
```
## 测试
```
java
public
class
Test
{
public
static
void
main
(
String
[]
args
)
{
Account
account
=
new
DiyAccount
(
10000
);
Account
.
demo
(
account
);
}
}
```
输出
```
0 cost: 65 ms
```
## 其它——Unsafe工具类UnsafeAccessor
我们知道
`Unsafe `
的构造方法是私有的,也没有
`get`
方法可以获取对象,所以我们只能通过反射的方式来实例化
`Unsafe`
对象。
```
java
public
final
class
Unsafe
{
private
static
final
Unsafe
theUnsafe
;
private
Unsafe
()
{
}
...
}
```
所以
```
java
import
sun.misc.Unsafe
;
import
java.lang.reflect.Field
;
public
class
UnsafeAccessor
{
private
static
final
Unsafe
unsafe
;
static
{
try
{
Field
theUnsafe
=
Unsafe
.
class
.
getDeclaredField
(
"theUnsafe"
);
theUnsafe
.
setAccessible
(
true
);
unsafe
=
(
Unsafe
)
theUnsafe
.
get
(
null
);
}
catch
(
NoSuchFieldException
|
IllegalAccessException
e
)
{
throw
new
Error
(
e
);
}
}
public
static
Unsafe
getUnsafe
()
{
return
unsafe
;
}
}
```
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录