Skip to content

Commit a18a127

Browse files
author
zhangml
committed
add synchronized detail
1 parent 925ba46 commit a18a127

File tree

10 files changed

+93
-25
lines changed

10 files changed

+93
-25
lines changed

READEME.md

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,45 @@ public class Singleton {
8787
* [代码示例](https://github.com/Fadezed/concurrency/blob/master/src/main/java/com/example/concurrency/volatileExample/VolatileExample.java)
8888

8989
* ## synchronized
90+
91+
* JVM 中的同步是基于进入和退出管程(Monitor)对象实现的。每个对象实例都会有一个 Monitor,Monitor 可以和对象一起创建、销毁。Monitor 是由 ObjectMonitor 实现,而 ObjectMonitor 实现,而 ObjectMonitor 是由C++ 的 ObjectMonitor.hpp 文件实现
92+
93+
`当多个线程同时访问时,多个线程会被先放在EntryList集合,处于block状态的线程,都会被加入到该列表。接下来当线程获取到对象的Monitor时,Monitor依靠底层操作系统的Mutex Lock来实现互斥,线程申请Mutex成功则持有,其它线程无法获取到Mutex`
94+
```
95+
ObjectMonitor() {
96+
_header = NULL;
97+
_count = 0; // 记录个数
98+
_waiters = 0,
99+
_recursions = 0;
100+
_object = NULL;
101+
_owner = NULL;
102+
_WaitSet = NULL; // 处于 wait 状态的线程,会被加入到 _WaitSet
103+
_WaitSetLock = 0 ;
104+
_Responsible = NULL ;
105+
_succ = NULL ;
106+
_cxq = NULL ;
107+
FreeNext = NULL ;
108+
_EntryList = NULL ; // 处于等待锁 block 状态的线程,会被加入到该列表
109+
_SpinFreq = 0 ;
110+
_SpinClock = 0 ;
111+
OwnerIsThread = 0 ;
112+
}
113+
```
114+
115+
* wait():如果线程调用 wait() 方法,就会释放当前持有的 Mutex,并且该线程会进入 WaitSet 集合中,等待下一次被唤醒。如果当前线程顺利执行完方法,也将释放 Mutex。
116+
![waitSet](media/15604993692307/waitSet.png)
117+
118+
* 锁升级优化
119+
* jdk1.6引入Java对象头(MarkWord、指向类的指针以及数组长度三部分组成)
120+
121+
`对象实例分为对象头、实例数据和对齐填充`
122+
* 64位JVM中MarkWord的存储结构
123+
![markWord](media/15604993692307/markWord.jpg)
124+
* 偏向锁
125+
* 轻量级锁
126+
* 重量级锁
127+
128+
90129
* [代码示例](https://github.com/Fadezed/concurrency/blob/master/src/main/java/com/example/concurrency/synchronizedEx/SynchronizedExample.java)
91130
92131
```
@@ -106,23 +145,26 @@ public class Singleton {
106145
}
107146
108147
```
109-
* ## final
110-
111-
* [代码示例](https://github.com/Fadezed/concurrency/blob/master/src/main/java/com/example/concurrency/finalEx/FinalExample.java)
112148
113-
`修饰变量时,初衷是告诉编译器:这个变量生而不变。`
149+
## final
150+
151+
* [代码示例](https://github.com/Fadezed/concurrency/blob/master/src/main/java/com/example/concurrency/finalEx/FinalExample.java)
152+
153+
`修饰变量时,初衷是告诉编译器:这个变量生而不变。`
114154
115-
```
155+
156+
```
116157
final int x;
117158
// 错误的构造函数
118159
public FinalFieldExample() {
119-
x = 3;
120-
y = 4;
121-
// 此处就是讲 this 逸出,
122-
global.obj = this;
160+
x = 3;
161+
y = 4;
162+
// 此处就是讲 this 逸出,
163+
global.obj = this;
123164
}
124165

125-
```
166+
167+
```
126168
127169
* ## Happens-Before六大规则
128170
1. **程序的顺序性规则**
@@ -620,11 +662,11 @@ ThreadPoolExecutor(
620662
这个方法的参数是一个 Runnable 接口,Runnable 接口的 run() 方法是没有返回值的,所以 submit(Runnable task) 这个方法返回的 Future 仅可以用来断言任务已经结束了,类似于 Thread.join()。
621663
```
622664
623-
* <T> Future<T> submit(Callable<T> task);// 提交 Callable 任务
665+
* <T> Future <T> submit(Callable <T> task);// 提交 Callable 任务
624666
```
625667
Callable只有一个 call() 方法,并且这个方法是有返回值的,所以这个方法返回的 Future 对象可以通过调用其 get() 方法来获取任务的执行结果。
626668
```
627-
* <T> Future<T> submit(Runnable task, T result);// 提交 Runnable 任务及结果引用
669+
* <T> Future <T> submit(Runnable task, T result);// 提交 Runnable 任务及结果引用
628670
```
629671
假设这个方法返回的 Future 对象是 f,f.get()=的返回值就是传给 submit() 方法的参数 result。
630672
```

media/15604993692307/markWord.jpg

77.5 KB
Loading

media/15604993692307/waitSet.png

46.7 KB
Loading

src/main/java/com/example/concurrency/deadLock/DeadLockTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class DeadLockTest {
1818
private ThreadDumpHelper dumpHelper = new ThreadDumpHelper();
1919
/**
2020
* 事实上String 对象不建议当成锁的对象(常量池的存在会导致锁重复)
21-
* 这里故意讲A、B放入堆中以示问题
21+
* 这里故意将A、B放入堆中以示问题
2222
*/
2323
private static String A = new String("A");
2424
private static String B = new String("B");

src/main/java/com/example/concurrency/finalEx/FinalExample.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
* @since 2019-06-13 1:38 PM
1010
*/
1111
public class FinalExample {
12-
static class Global{
12+
private static class Global{
1313
private static FinalExample example;
1414

1515
}
16-
final int x;
17-
int y;
18-
static FinalExample f;
16+
private final int x;
17+
private int y;
18+
private static FinalExample f;
1919
// public FinalExample() {
2020
// x = 3;
2121
// y = 4;
@@ -28,11 +28,11 @@ public FinalExample() { // bad!
2828
Global.example = this;
2929
}
3030

31-
static void writer() {
31+
private static void writer() {
3232
f = new FinalExample();
3333
}
3434

35-
static void reader() {
35+
private static void reader() {
3636
if (f != null) {
3737
int i = f.x;
3838
int j = f.y;

src/main/java/com/example/concurrency/readWriteLock/CacheByReadWriteLock.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* 描述:
1111
* 读写锁实现缓存
1212
*
13-
* ReentrantReadWriteLock 只支持锁的降级 不支持锁升级 并且只有写锁可以创建呢条件变量
13+
* ReentrantReadWriteLock 只支持锁的降级 不支持锁升级 并且只有写锁可以创建条件变量
1414
* 读写锁允许多个线程同时读共享变量,当一个线程在写共享变量的时候,是不允许其他线程执行写操作和读操作。
1515
*
1616
*

src/main/java/com/example/concurrency/readWriteLock/StampedLockEx.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/**
66
* 描述:
77
* StampedLockEx
8-
* 写锁和悲观锁 跟ReentrantReadWriteLock 类似,非可重入锁
8+
* 写锁和悲观锁 跟ReentrantReadWriteLock 类似,非可重入锁,并且不支持条件变量
99
* ReadWriteLock 支持多个线程同时读,但是当多个线个线程同时读的时候,
1010
* 所有的写操作会被阻塞;而 StampedLock 提供的乐观读(无锁),是允许一个线程获取写锁的,也就是说不是所有的写操作都被阻塞。
1111
*

src/main/java/com/example/concurrency/singleton/StaticSingleton.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public class StaticSingleton {
77

88
private StaticSingleton(){
99
}
10-
public static class StaticSingletonHolder{
10+
private static class StaticSingletonHolder{
1111
private static StaticSingleton singleton= new StaticSingleton();
1212
}
1313
public static StaticSingleton getInstance(){

src/main/java/com/example/concurrency/synchronizedEx/SynchronizedExample.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,39 @@
55

66
/**
77
* 描述:
8-
* Synchronized
8+
* Synchronized 实现原理 基于操作系统Mutex Lock (互斥锁)实现,所以每次获取和释放都会由用户态和内核态的切换成本高,jdk1.5之前性能差
9+
* JVM通过ACC_SYNCHRONIZED 标识一个方法是否为同步方法,而代码块则通过monitorenter和monitorexit指令操作monitor对象
910
*
10-
* @author zed
11+
*
12+
*
13+
** @author zed
1114
* @since 2019-06-13 11:47 AM
1215
*/
1316
public class SynchronizedExample {
1417

18+
static class X {
19+
/**
20+
* 修饰非静态方法 锁对象为当前类的实例对象 this
21+
*/
22+
synchronized void get() {
23+
}
24+
25+
/**
26+
* 修饰静态方法 锁对象为当前类的Class对象 Class X
27+
*/
28+
synchronized static void set() {
29+
}
30+
31+
/**
32+
* 修饰代码块
33+
*/
34+
Object obj = new Object();
35+
void put() {
36+
synchronized(obj) {
37+
}
38+
}
39+
}
40+
1541
/**
1642
* 利用Synchronized 实现原子操作
1743
*/

src/main/java/com/example/concurrency/visibility/Visibility.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ private static long calc(){
3838
}catch (InterruptedException e){
3939
Thread.currentThread().interrupt();
4040
}
41-
return visibility.count;
41+
return count;
4242
}
4343

4444
}

0 commit comments

Comments
 (0)